diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index a39bfe00be28f6f60c4211826b23165059ee00a4..68a0e9cc1bf8377526ed80d91d9f8936d3de3143 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone import android.app.StatusBarManager.WINDOW_STATUS_BAR import android.graphics.Point import android.util.Log +import android.view.InputDevice import android.view.MotionEvent import android.view.View import android.view.ViewGroup @@ -81,7 +82,22 @@ private constructor( statusContainer.setOnHoverListener( statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer) ) - statusContainer.setOnClickListener { shadeViewController.expand(/* animate= */true) } + statusContainer.setOnTouchListener(object : View.OnTouchListener { + override fun onTouch(v: View, event: MotionEvent): Boolean { + // We want to handle only mouse events here to avoid stealing finger touches from + // status bar which expands shade when swiped down on. We're using onTouchListener + // instead of onClickListener as the later will lead to isClickable being set to + // true and hence ALL touches always being intercepted. See [View.OnTouchEvent] + if (event.source == InputDevice.SOURCE_MOUSE) { + if (event.action == MotionEvent.ACTION_UP) { + v.performClick() + shadeViewController.expand(/* animate= */ true) + } + return true + } + return false + } + }) progressProvider?.setReadyToHandleTransition(true) configurationController.addCallback(configurationListener) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 1687ccbf5826f86a6f66e64d4b7f52ae78d1e89b..3792d5c1d6b987cd039fa24af704dc816398fb7d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -20,6 +20,7 @@ import android.app.StatusBarManager.WINDOW_STATE_HIDDEN import android.app.StatusBarManager.WINDOW_STATE_HIDING import android.app.StatusBarManager.WINDOW_STATE_SHOWING import android.app.StatusBarManager.WINDOW_STATUS_BAR +import android.view.InputDevice import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -239,10 +240,41 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { controller = createAndInitController(view) } val statusContainer = view.requireViewById<View>(R.id.system_icons) - statusContainer.performClick() + statusContainer.dispatchTouchEvent( + getMotionEventFromSource( + MotionEvent.ACTION_UP, + 0, + 0, + InputDevice.SOURCE_MOUSE + ) + ) verify(shadeViewController).expand(any()) } + @Test + fun statusIconContainerIsNotHandlingTouchScreenTouches() { + val view = createViewMock() + InstrumentationRegistry.getInstrumentation().runOnMainSync { + controller = createAndInitController(view) + } + val statusContainer = view.requireViewById<View>(R.id.system_icons) + val handled = statusContainer.dispatchTouchEvent( + getMotionEventFromSource( + MotionEvent.ACTION_UP, + 0, + 0, + InputDevice.SOURCE_TOUCHSCREEN + ) + ) + assertThat(handled).isFalse() + } + + private fun getMotionEventFromSource(action: Int, x: Int, y: Int, source: Int): MotionEvent { + val ev = MotionEvent.obtain(0, 0, action, x.toFloat(), y.toFloat(), 0) + ev.source = source + return ev + } + @Test fun shadeIsNotExpandedOnStatusBarGeneralClick() { val view = createViewMock()