diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt index 6ec2b6e89cb0e..15b8f13ee0f89 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt @@ -22,6 +22,7 @@ import android.content.Context import android.graphics.PixelFormat import android.view.Gravity import android.view.LayoutInflater +import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.WindowManager @@ -31,6 +32,7 @@ import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.view.ViewUtil /** * A superclass controller that provides common functionality for showing chips on the sender device @@ -42,6 +44,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor abstract class MediaTttChipControllerCommon( internal val context: Context, private val windowManager: WindowManager, + private val viewUtil: ViewUtil, @Main private val mainExecutor: DelayableExecutor, private val tapGestureDetector: TapGestureDetector, @LayoutRes private val chipLayoutRes: Int @@ -84,7 +87,7 @@ abstract class MediaTttChipControllerCommon( // Add view if necessary if (oldChipView == null) { - tapGestureDetector.addOnGestureDetectedCallback(TAG, this::removeChip) + tapGestureDetector.addOnGestureDetectedCallback(TAG, this::onScreenTapped) windowManager.addView(chipView, windowLayoutParams) } @@ -127,6 +130,15 @@ abstract class MediaTttChipControllerCommon( appIconView.setImageDrawable(appIcon) appIconView.visibility = visibility } + + private fun onScreenTapped(e: MotionEvent) { + val view = chipView ?: return + // If the tap is within the chip bounds, we shouldn't hide the chip (in case users think the + // chip is tappable). + if (!viewUtil.touchIsWithinView(view, e.x, e.y)) { + removeChip() + } + } } // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index b6f1aea9a384d..3d43ebe817428 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -31,6 +31,7 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCom import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -43,11 +44,17 @@ class MediaTttChipControllerReceiver @Inject constructor( commandQueue: CommandQueue, context: Context, windowManager: WindowManager, + viewUtil: ViewUtil, mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, @Main private val mainHandler: Handler, ) : MediaTttChipControllerCommon( - context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip_receiver + context, + windowManager, + viewUtil, + mainExecutor, + tapGestureDetector, + R.layout.media_ttt_chip_receiver ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferReceiverDisplay( diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt index fef17fdcbbdc0..180e4ee9726c2 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt @@ -32,6 +32,7 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCom import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -43,10 +44,11 @@ class MediaTttChipControllerSender @Inject constructor( commandQueue: CommandQueue, context: Context, windowManager: WindowManager, + viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, ) : MediaTttChipControllerCommon( - context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip + context, windowManager, viewUtil, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip ) { private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferSenderDisplay( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt index 76766b0d0ef04..3a4731a5a6aa3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt @@ -22,6 +22,7 @@ import android.os.Looper import android.view.Choreographer import android.view.Display import android.view.InputEvent +import android.view.MotionEvent import com.android.systemui.shared.system.InputChannelCompat import com.android.systemui.shared.system.InputMonitorCompat @@ -43,13 +44,17 @@ abstract class GenericGestureDetector( * Active callbacks, each associated with a tag. Gestures will only be monitored if * [callbacks.size] > 0. */ - private val callbacks: MutableMap Unit> = mutableMapOf() + private val callbacks: MutableMap Unit> = mutableMapOf() private var inputMonitor: InputMonitorCompat? = null private var inputReceiver: InputChannelCompat.InputEventReceiver? = null - /** Adds a callback that will be triggered when the tap gesture is detected. */ - fun addOnGestureDetectedCallback(tag: String, callback: () -> Unit) { + /** + * Adds a callback that will be triggered when the tap gesture is detected. + * + * The callback receive the last motion event in the gesture. + */ + fun addOnGestureDetectedCallback(tag: String, callback: (MotionEvent) -> Unit) { val callbacksWasEmpty = callbacks.isEmpty() callbacks[tag] = callback if (callbacksWasEmpty) { @@ -68,9 +73,12 @@ abstract class GenericGestureDetector( /** Triggered each time a touch event occurs (and at least one callback is registered). */ abstract fun onInputEvent(ev: InputEvent) - /** Should be called by subclasses when their specific gesture is detected. */ - internal fun onGestureDetected() { - callbacks.values.forEach { it.invoke() } + /** + * Should be called by subclasses when their specific gesture is detected with the last motion + * event in the gesture. + */ + internal fun onGestureDetected(e: MotionEvent) { + callbacks.values.forEach { it.invoke(e) } } /** Start listening to touch events. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt index fcb285a50ae72..6115819b967aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt @@ -80,7 +80,7 @@ open class SwipeStatusBarAwayGestureHandler @Inject constructor( ) { monitoringCurrentTouch = false logger.logGestureDetected(ev.y.toInt()) - onGestureDetected() + onGestureDetected(ev) } } ACTION_CANCEL, ACTION_UP -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt index 4107ce2593f1a..7ffb07aa77d00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt @@ -33,8 +33,8 @@ class TapGestureDetector @Inject constructor( ) : GenericGestureDetector(TapGestureDetector::class.simpleName!!) { private val gestureListener = object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapUp(e: MotionEvent?): Boolean { - onGestureDetected() + override fun onSingleTapUp(e: MotionEvent): Boolean { + onGestureDetected(e) return true } } 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 224b2e45bfe59..9da2ef734be87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -31,6 +31,7 @@ import com.android.systemui.unfold.UNFOLD_STATUS_BAR import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider import com.android.systemui.util.ViewController import com.android.systemui.util.kotlin.getOrNull +import com.android.systemui.util.view.ViewUtil import java.util.Optional @@ -43,6 +44,7 @@ class PhoneStatusBarViewController private constructor( @Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?, private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?, private val userSwitcherController: StatusBarUserSwitcherController, + private val viewUtil: ViewUtil, touchEventHandler: PhoneStatusBarView.TouchEventHandler, private val configurationController: ConfigurationController ) : ViewController(view) { @@ -118,12 +120,7 @@ class PhoneStatusBarViewController private constructor( * view's range and false otherwise. */ fun touchIsWithinView(x: Float, y: Float): Boolean { - val left = mView.locationOnScreen[0] - val top = mView.locationOnScreen[1] - return left <= x && - x <= left + mView.width && - top <= y && - y <= top + mView.height + return viewUtil.touchIsWithinView(mView, x, y) } class StatusBarViewsCenterProvider : UnfoldMoveFromCenterAnimator.ViewCenterProvider { @@ -163,6 +160,7 @@ class PhoneStatusBarViewController private constructor( @Named(UNFOLD_STATUS_BAR) private val progressProvider: Optional, private val userSwitcherController: StatusBarUserSwitcherController, + private val viewUtil: ViewUtil, private val configurationController: ConfigurationController ) { fun create( @@ -174,6 +172,7 @@ class PhoneStatusBarViewController private constructor( progressProvider.getOrNull(), unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(), userSwitcherController, + viewUtil, touchEventHandler, configurationController ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index 6e7231ef5ca38..fb75f259c08a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -306,7 +306,7 @@ class OngoingCallController @Inject constructor( swipeStatusBarAwayGestureHandler.ifPresent { it.removeOnGestureDetectedCallback(TAG) } } else { swipeStatusBarAwayGestureHandler.ifPresent { - it.addOnGestureDetectedCallback(TAG, this::onSwipeAwayGestureDetected) + it.addOnGestureDetectedCallback(TAG) { _ -> onSwipeAwayGestureDetected() } } } } diff --git a/packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt b/packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt new file mode 100644 index 0000000000000..613a797f020c5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt @@ -0,0 +1,26 @@ +package com.android.systemui.util.view + +import android.view.View +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject + +/** + * A class with generic view utility methods. + * + * Doesn't use static methods so that it can be easily mocked out in tests. + */ +@SysUISingleton +class ViewUtil @Inject constructor() { + /** + * Returns true if the given (x, y) point (in screen coordinates) is within the status bar + * view's range and false otherwise. + */ + fun touchIsWithinView(view: View, x: Float, y: Float): Boolean { + val left = view.locationOnScreen[0] + val top = view.locationOnScreen[1] + return left <= x && + x <= left + view.width && + top <= y && + y <= top + view.height + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt index 28de17664df1d..809b8901f8675 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.taptotransfer.common import android.content.Context import android.graphics.drawable.Drawable +import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.WindowManager @@ -30,7 +31,10 @@ import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.capture import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -39,6 +43,7 @@ import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest @@ -52,6 +57,8 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock + private lateinit var viewUtil: ViewUtil + @Mock private lateinit var tapGestureDetector: TapGestureDetector @Before @@ -62,7 +69,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { fakeExecutor = FakeExecutor(fakeClock) controllerCommon = TestControllerCommon( - context, windowManager, fakeExecutor, tapGestureDetector + context, windowManager, viewUtil, fakeExecutor, tapGestureDetector ) } @@ -169,6 +176,40 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { .isEqualTo(state.getAppName(context)) } + @Test + fun tapGestureDetected_outsideViewBounds_viewHidden() { + controllerCommon.displayChip(getState()) + whenever(viewUtil.touchIsWithinView(any(), any(), any())).thenReturn(false) + val gestureCallbackCaptor = argumentCaptor<(MotionEvent) -> Unit>() + verify(tapGestureDetector).addOnGestureDetectedCallback( + any(), capture(gestureCallbackCaptor) + ) + val callback = gestureCallbackCaptor.value!! + + callback.invoke( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + ) + + verify(windowManager).removeView(any()) + } + + @Test + fun tapGestureDetected_insideViewBounds_viewNotHidden() { + controllerCommon.displayChip(getState()) + whenever(viewUtil.touchIsWithinView(any(), any(), any())).thenReturn(true) + val gestureCallbackCaptor = argumentCaptor<(MotionEvent) -> Unit>() + verify(tapGestureDetector).addOnGestureDetectedCallback( + any(), capture(gestureCallbackCaptor) + ) + val callback = gestureCallbackCaptor.value!! + + callback.invoke( + MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + ) + + verify(windowManager, never()).removeView(any()) + } + private fun getState() = MediaTttChipState(PACKAGE_NAME) private fun getChipView(): ViewGroup { @@ -182,10 +223,11 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { inner class TestControllerCommon( context: Context, windowManager: WindowManager, + viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, tapGestureDetector: TapGestureDetector, ) : MediaTttChipControllerCommon( - context, windowManager, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip + context, windowManager, viewUtil, mainExecutor, tapGestureDetector, R.layout.media_ttt_chip ) { override fun updateChipView(chipState: MediaTttChipState, currentChipView: ViewGroup) { } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index e5f4df6c622a6..86d4c1b05ed33 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -37,6 +37,7 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -61,6 +62,8 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock + private lateinit var viewUtil: ViewUtil + @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -81,6 +84,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { commandQueue, context, windowManager, + viewUtil, FakeExecutor(FakeSystemClock()), TapGestureDetector(context), Handler.getMain(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt index e5ba3f3d87bf0..88888f0da0f76 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -38,6 +38,8 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.view.ViewUtil + import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -62,6 +64,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock + private lateinit var viewUtil: ViewUtil + @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -82,6 +86,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { commandQueue, context, windowManager, + viewUtil, FakeExecutor(FakeSystemClock()), TapGestureDetector(context) ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt index c0389034b4f23..ea066471a802a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt @@ -111,7 +111,7 @@ class GenericGestureDetectorTest : SysuiTestCase() { override fun onInputEvent(ev: InputEvent) { if (ev is MotionEvent && ev.x == CORRECT_X) { - onGestureDetected() + onGestureDetected(ev) } } 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 5891161847103..9ab88dc2d7646 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 @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.unfold.SysUIUnfoldComponent import com.android.systemui.unfold.config.UnfoldTransitionConfig import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider +import com.android.systemui.util.view.ViewUtil import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -63,6 +64,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { private lateinit var configurationController: ConfigurationController @Mock private lateinit var userSwitcherController: StatusBarUserSwitcherController + @Mock + private lateinit var viewUtil: ViewUtil private lateinit var view: PhoneStatusBarView private lateinit var controller: PhoneStatusBarViewController @@ -80,7 +83,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { val parent = FrameLayout(mContext) // add parent to keep layout params view = LayoutInflater.from(mContext) .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView - view.setLeftTopRightBottom(VIEW_LEFT, VIEW_TOP, VIEW_RIGHT, VIEW_BOTTOM) } controller = createAndInitController(view) @@ -111,64 +113,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { verify(moveFromCenterAnimation).onViewsReady(any()) } - @Test - fun touchIsWithinView_inBounds_returnsTrue() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_LEFT + 1f, VIEW_TOP + 1f)).isTrue() - } - - @Test - fun touchIsWithinView_onTopLeftCorner_returnsTrue() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_LEFT.toFloat(), VIEW_TOP.toFloat())).isTrue() - } - - @Test - fun touchIsWithinView_onBottomRightCorner_returnsTrue() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView( - VIEW_RIGHT.toFloat(), VIEW_BOTTOM.toFloat()) - ).isTrue() - } - - @Test - fun touchIsWithinView_xTooSmall_returnsFalse() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_LEFT - 1f, VIEW_TOP + 1f)).isFalse() - } - - @Test - fun touchIsWithinView_xTooLarge_returnsFalse() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_RIGHT + 1f, VIEW_TOP + 1f)).isFalse() - } - - @Test - fun touchIsWithinView_yTooSmall_returnsFalse() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_LEFT + 1f, VIEW_TOP - 1f)).isFalse() - } - - @Test - fun touchIsWithinView_yTooLarge_returnsFalse() { - val view = createViewMockWithScreenLocation() - controller = createAndInitController(view) - - assertThat(controller.touchIsWithinView(VIEW_LEFT + 1f, VIEW_BOTTOM + 1f)).isFalse() - } - private fun createViewMock(): PhoneStatusBarView { val view = spy(view) val viewTreeObserver = mock(ViewTreeObserver::class.java) @@ -177,20 +121,12 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { return view } - private fun createViewMockWithScreenLocation(): PhoneStatusBarView { - val view = spy(view) - val location = IntArray(2) - location[0] = VIEW_LEFT - location[1] = VIEW_TOP - `when`(view.locationOnScreen).thenReturn(location) - return view - } - private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController { return PhoneStatusBarViewController.Factory( Optional.of(sysuiUnfoldComponent), Optional.of(progressProvider), userSwitcherController, + viewUtil, configurationController ).create(view, touchEventHandler).also { it.init() @@ -215,8 +151,3 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { } } } - -private const val VIEW_LEFT = 30 -private const val VIEW_RIGHT = 100 -private const val VIEW_TOP = 40 -private const val VIEW_BOTTOM = 100 diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt new file mode 100644 index 0000000000000..dead1592992d7 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt @@ -0,0 +1,72 @@ +package com.android.systemui.util.view + +import android.view.View +import android.widget.TextView +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito.spy +import org.mockito.Mockito.`when` + +@SmallTest +class ViewUtilTest : SysuiTestCase() { + private val viewUtil = ViewUtil() + private lateinit var view: View + + @Before + fun setUp() { + view = TextView(context) + view.setLeftTopRightBottom(VIEW_LEFT, VIEW_TOP, VIEW_RIGHT, VIEW_BOTTOM) + + view = spy(view) + val location = IntArray(2) + location[0] = VIEW_LEFT + location[1] = VIEW_TOP + `when`(view.locationOnScreen).thenReturn(location) + } + + @Test + fun touchIsWithinView_inBounds_returnsTrue() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_LEFT + 1f, VIEW_TOP + 1f)).isTrue() + } + + @Test + fun touchIsWithinView_onTopLeftCorner_returnsTrue() { + assertThat(viewUtil.touchIsWithinView( + view, VIEW_LEFT.toFloat(), VIEW_TOP.toFloat()) + ).isTrue() + } + + @Test + fun touchIsWithinView_onBottomRightCorner_returnsTrue() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_RIGHT.toFloat(), VIEW_BOTTOM.toFloat())) + .isTrue() + } + + @Test + fun touchIsWithinView_xTooSmall_returnsFalse() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_LEFT - 1f, VIEW_TOP + 1f)).isFalse() + } + + @Test + fun touchIsWithinView_xTooLarge_returnsFalse() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_RIGHT + 1f, VIEW_TOP + 1f)).isFalse() + } + + @Test + fun touchIsWithinView_yTooSmall_returnsFalse() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_LEFT + 1f, VIEW_TOP - 1f)).isFalse() + } + + @Test + fun touchIsWithinView_yTooLarge_returnsFalse() { + assertThat(viewUtil.touchIsWithinView(view, VIEW_LEFT + 1f, VIEW_BOTTOM + 1f)).isFalse() + } +} + +private const val VIEW_LEFT = 30 +private const val VIEW_RIGHT = 100 +private const val VIEW_TOP = 40 +private const val VIEW_BOTTOM = 100