Merge "Multi-shade foundation - integration (5/5)." into udc-dev
diff --git a/packages/SystemUI/res/layout/multi_shade.xml b/packages/SystemUI/res/layout/multi_shade.xml
new file mode 100644
index 0000000..78ff5f0
--- /dev/null
+++ b/packages/SystemUI/res/layout/multi_shade.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<com.android.systemui.multishade.ui.view.MultiShadeView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index 4abc176..fe9542b 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -110,6 +110,13 @@
android:clipChildren="false"
android:clipToPadding="false" />
+ <ViewStub
+ android:id="@+id/multi_shade_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:inflatedId="@+id/multi_shade"
+ android:layout="@layout/multi_shade" />
+
<com.android.systemui.biometrics.AuthRippleView
android:id="@+id/auth_ripple"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/ui/view/MultiShadeView.kt b/packages/SystemUI/src/com/android/systemui/multishade/ui/view/MultiShadeView.kt
new file mode 100644
index 0000000..aecec39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/ui/view/MultiShadeView.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.multishade.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.compose.ComposeFacade
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
+import com.android.systemui.multishade.ui.viewmodel.MultiShadeViewModel
+import com.android.systemui.util.time.SystemClock
+import kotlinx.coroutines.launch
+
+/**
+ * View that hosts the multi-shade system and acts as glue between legacy code and the
+ * implementation.
+ */
+class MultiShadeView(
+ context: Context,
+ attrs: AttributeSet?,
+) :
+ FrameLayout(
+ context,
+ attrs,
+ ) {
+
+ fun init(
+ interactor: MultiShadeInteractor,
+ clock: SystemClock,
+ ) {
+ repeatWhenAttached {
+ lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ addView(
+ ComposeFacade.createMultiShadeView(
+ context = context,
+ viewModel =
+ MultiShadeViewModel(
+ viewModelScope = this,
+ interactor = interactor,
+ ),
+ clock = clock,
+ )
+ )
+ }
+
+ // Here when destroyed.
+ removeAllViews()
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 2899081..a716a6e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -23,7 +23,6 @@
import android.media.AudioManager;
import android.media.session.MediaSessionLegacyHelper;
import android.os.PowerManager;
-import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
@@ -31,6 +30,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.AuthKeyguardMessageArea;
@@ -39,8 +39,10 @@
import com.android.systemui.R;
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dock.DockManager;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -49,6 +51,8 @@
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor;
+import com.android.systemui.multishade.ui.view.MultiShadeView;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationInsetsController;
@@ -63,11 +67,13 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.util.function.Consumer;
import javax.inject.Inject;
+import javax.inject.Provider;
/**
* Controller for {@link NotificationShadeWindowView}.
@@ -115,6 +121,7 @@
mIsOcclusionTransitionRunning =
step.getTransitionState() == TransitionState.RUNNING;
};
+ private final SystemClock mClock;
@Inject
public NotificationShadeWindowViewController(
@@ -142,7 +149,9 @@
UdfpsOverlayInteractor udfpsOverlayInteractor,
KeyguardTransitionInteractor keyguardTransitionInteractor,
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ Provider<MultiShadeInteractor> multiShadeInteractorProvider,
+ SystemClock clock) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController;
@@ -175,6 +184,16 @@
collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
mLockscreenToDreamingTransition);
+
+ mClock = clock;
+ if (ComposeFacade.INSTANCE.isComposeAvailable()
+ && featureFlags.isEnabled(Flags.DUAL_SHADE)) {
+ final ViewStub multiShadeViewStub = mView.findViewById(R.id.multi_shade_stub);
+ if (multiShadeViewStub != null) {
+ final MultiShadeView multiShadeView = (MultiShadeView) multiShadeViewStub.inflate();
+ multiShadeView.init(multiShadeInteractorProvider.get(), clock);
+ }
+ }
}
/**
@@ -269,7 +288,7 @@
mLockIconViewController.onTouchEvent(
ev,
() -> mService.wakeUpIfDozing(
- SystemClock.uptimeMillis(),
+ mClock.uptimeMillis(),
mView,
"LOCK_ICON_TOUCH",
PowerManager.WAKE_REASON_GESTURE)
@@ -453,7 +472,7 @@
public void cancelCurrentTouch() {
if (mTouchActive) {
- final long now = SystemClock.uptimeMillis();
+ final long now = mClock.uptimeMillis();
final MotionEvent event;
if (mIsTrackpadGestureBackEnabled) {
event = MotionEvent.obtain(mDownEvent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 0dc2d17..bdb0e7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -37,6 +37,9 @@
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.data.repository.MultiShadeRepository
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.NotificationInsetsController
@@ -50,8 +53,12 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -65,10 +72,12 @@
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
+
@Mock private lateinit var view: NotificationShadeWindowView
@Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
@Mock private lateinit var centralSurfaces: CentralSurfaces
@@ -102,6 +111,8 @@
private lateinit var underTest: NotificationShadeWindowViewController
+ private lateinit var testScope: TestScope
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -115,8 +126,12 @@
whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
.thenReturn(emptyFlow<TransitionStep>())
- val featureFlags = FakeFeatureFlags();
+ val featureFlags = FakeFeatureFlags()
featureFlags.set(Flags.TRACKPAD_GESTURE_BACK, false)
+ featureFlags.set(Flags.DUAL_SHADE, false)
+
+ val inputProxy = MultiShadeInputProxy()
+ testScope = TestScope()
underTest =
NotificationShadeWindowViewController(
lockscreenShadeTransitionController,
@@ -144,6 +159,18 @@
keyguardTransitionInteractor,
primaryBouncerToGoneTransitionViewModel,
featureFlags,
+ {
+ MultiShadeInteractor(
+ applicationScope = testScope.backgroundScope,
+ repository =
+ MultiShadeRepository(
+ applicationContext = context,
+ inputProxy = inputProxy,
+ ),
+ inputProxy = inputProxy,
+ )
+ },
+ FakeSystemClock(),
)
underTest.setupExpandedStatusBar()
@@ -156,147 +183,162 @@
// tests need to be added to test the rest of handleDispatchTouchEvent.
@Test
- fun handleDispatchTouchEvent_nullStatusBarViewController_returnsFalse() {
- underTest.setStatusBarViewController(null)
+ fun handleDispatchTouchEvent_nullStatusBarViewController_returnsFalse() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(null)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- assertThat(returnVal).isFalse()
- }
+ assertThat(returnVal).isFalse()
+ }
@Test
- fun handleDispatchTouchEvent_downTouchBelowView_sendsTouchToSb() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- val ev = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
- whenever(phoneStatusBarViewController.sendTouchToView(ev)).thenReturn(true)
+ fun handleDispatchTouchEvent_downTouchBelowView_sendsTouchToSb() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ val ev = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
+ whenever(phoneStatusBarViewController.sendTouchToView(ev)).thenReturn(true)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(ev)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(ev)
- verify(phoneStatusBarViewController).sendTouchToView(ev)
- assertThat(returnVal).isTrue()
- }
+ verify(phoneStatusBarViewController).sendTouchToView(ev)
+ assertThat(returnVal).isTrue()
+ }
@Test
- fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- val downEvBelow =
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
- interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
+ fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ val downEvBelow =
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
+ interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
- val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
- whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
+ val nextEvent =
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
+ whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
- verify(phoneStatusBarViewController).sendTouchToView(nextEvent)
- assertThat(returnVal).isTrue()
- }
+ verify(phoneStatusBarViewController).sendTouchToView(nextEvent)
+ assertThat(returnVal).isTrue()
+ }
@Test
- fun handleDispatchTouchEvent_downAndPanelCollapsedAndInSbBoundAndSbWindowShow_sendsTouchToSb() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
- whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
- whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
- .thenReturn(true)
- whenever(phoneStatusBarViewController.sendTouchToView(downEv)).thenReturn(true)
+ fun handleDispatchTouchEvent_downAndPanelCollapsedAndInSbBoundAndSbWindowShow_sendsTouchToSb() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
+ whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
+ .thenReturn(true)
+ whenever(phoneStatusBarViewController.sendTouchToView(DOWN_EVENT)).thenReturn(true)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- verify(phoneStatusBarViewController).sendTouchToView(downEv)
- assertThat(returnVal).isTrue()
- }
+ verify(phoneStatusBarViewController).sendTouchToView(DOWN_EVENT)
+ assertThat(returnVal).isTrue()
+ }
@Test
- fun handleDispatchTouchEvent_panelNotCollapsed_returnsNull() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
- whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
- .thenReturn(true)
- // Item we're testing
- whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(false)
+ fun handleDispatchTouchEvent_panelNotCollapsed_returnsNull() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
+ whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
+ .thenReturn(true)
+ // Item we're testing
+ whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(false)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- verify(phoneStatusBarViewController, never()).sendTouchToView(downEv)
- assertThat(returnVal).isNull()
- }
+ verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
+ assertThat(returnVal).isNull()
+ }
@Test
- fun handleDispatchTouchEvent_touchNotInSbBounds_returnsNull() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
- whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
- // Item we're testing
- whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
- .thenReturn(false)
+ fun handleDispatchTouchEvent_touchNotInSbBounds_returnsNull() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
+ whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ // Item we're testing
+ whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
+ .thenReturn(false)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- verify(phoneStatusBarViewController, never()).sendTouchToView(downEv)
- assertThat(returnVal).isNull()
- }
+ verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
+ assertThat(returnVal).isNull()
+ }
@Test
- fun handleDispatchTouchEvent_sbWindowNotShowing_noSendTouchToSbAndReturnsTrue() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
- whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
- .thenReturn(true)
- // Item we're testing
- whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(false)
+ fun handleDispatchTouchEvent_sbWindowNotShowing_noSendTouchToSbAndReturnsTrue() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
+ .thenReturn(true)
+ // Item we're testing
+ whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(false)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- verify(phoneStatusBarViewController, never()).sendTouchToView(downEv)
- assertThat(returnVal).isTrue()
- }
+ verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
+ assertThat(returnVal).isTrue()
+ }
@Test
- fun handleDispatchTouchEvent_downEventSentToSbThenAnotherEvent_sendsTouchToSb() {
- underTest.setStatusBarViewController(phoneStatusBarViewController)
- whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
- whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
- whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
- .thenReturn(true)
+ fun handleDispatchTouchEvent_downEventSentToSbThenAnotherEvent_sendsTouchToSb() =
+ testScope.runTest {
+ underTest.setStatusBarViewController(phoneStatusBarViewController)
+ whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
+ whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
+ .thenReturn(true)
- // Down event first
- interactionEventHandler.handleDispatchTouchEvent(downEv)
+ // Down event first
+ interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
- // Then another event
- val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
- whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
+ // Then another event
+ val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
+ whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
- val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
+ val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
- verify(phoneStatusBarViewController).sendTouchToView(nextEvent)
- assertThat(returnVal).isTrue()
- }
+ verify(phoneStatusBarViewController).sendTouchToView(nextEvent)
+ assertThat(returnVal).isTrue()
+ }
@Test
- fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() {
- // Down event within udfpsOverlay bounds while alternateBouncer is showing
- whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(downEv)).thenReturn(false)
- whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
+ fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() =
+ testScope.runTest {
+ // Down event within udfpsOverlay bounds while alternateBouncer is showing
+ whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(DOWN_EVENT))
+ .thenReturn(false)
+ whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
- // Then touch should not be intercepted
- val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(downEv)
- assertThat(shouldIntercept).isFalse()
- }
+ // Then touch should not be intercepted
+ val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
+ assertThat(shouldIntercept).isFalse()
+ }
@Test
- fun testGetBouncerContainer() {
- Mockito.clearInvocations(view)
- underTest.bouncerContainer
- verify(view).findViewById<ViewGroup>(R.id.keyguard_bouncer_container)
- }
+ fun testGetBouncerContainer() =
+ testScope.runTest {
+ Mockito.clearInvocations(view)
+ underTest.bouncerContainer
+ verify(view).findViewById<ViewGroup>(R.id.keyguard_bouncer_container)
+ }
@Test
- fun testGetKeyguardMessageArea() {
- underTest.keyguardMessageArea
- verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area)
+ fun testGetKeyguardMessageArea() =
+ testScope.runTest {
+ underTest.keyguardMessageArea
+ verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area)
+ }
+
+ companion object {
+ private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+ private const val VIEW_BOTTOM = 100
}
}
-
-private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
-private const val VIEW_BOTTOM = 100
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
deleted file mode 100644
index 2797440..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
-import android.os.SystemClock;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.MotionEvent;
-import android.view.ViewGroup;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.keyguard.KeyguardSecurityContainerController;
-import com.android.keyguard.LockIconViewController;
-import com.android.keyguard.dagger.KeyguardBouncerComponent;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
-import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
-import com.android.systemui.statusbar.DragDownHelper;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationInsetsController;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.tuner.TunerService;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class NotificationShadeWindowViewTest extends SysuiTestCase {
-
- private NotificationShadeWindowView mView;
- private NotificationShadeWindowViewController mController;
-
- @Mock private TunerService mTunerService;
- @Mock private DragDownHelper mDragDownHelper;
- @Mock private SysuiStatusBarStateController mStatusBarStateController;
- @Mock private ShadeController mShadeController;
- @Mock private CentralSurfaces mCentralSurfaces;
- @Mock private DockManager mDockManager;
- @Mock private NotificationPanelViewController mNotificationPanelViewController;
- @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
- @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
- @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
- @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock private LockIconViewController mLockIconViewController;
- @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
- @Mock private AmbientState mAmbientState;
- @Mock private PulsingGestureListener mPulsingGestureListener;
- @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
- @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
- @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
- @Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
- @Mock private NotificationInsetsController mNotificationInsetsController;
- @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
- @Mock private UdfpsOverlayInteractor mUdfpsOverlayInteractor;
- @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
- @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
-
- @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
- mInteractionEventHandlerCaptor;
- private NotificationShadeWindowView.InteractionEventHandler mInteractionEventHandler;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mView = spy(new NotificationShadeWindowView(getContext(), null));
- when(mView.findViewById(R.id.notification_stack_scroller))
- .thenReturn(mNotificationStackScrollLayout);
-
- when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class));
- when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn(
- mKeyguardBouncerComponent);
- when(mKeyguardBouncerComponent.getSecurityContainerController()).thenReturn(
- mKeyguardSecurityContainerController);
-
- when(mStatusBarStateController.isDozing()).thenReturn(false);
- mDependency.injectTestDependency(ShadeController.class, mShadeController);
-
- when(mDockManager.isDocked()).thenReturn(false);
-
- when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
- .thenReturn(emptyFlow());
-
- FakeFeatureFlags featureFlags = new FakeFeatureFlags();
- featureFlags.set(Flags.TRACKPAD_GESTURE_BACK, false);
- mController = new NotificationShadeWindowViewController(
- mLockscreenShadeTransitionController,
- new FalsingCollectorFake(),
- mStatusBarStateController,
- mDockManager,
- mNotificationShadeDepthController,
- mView,
- mNotificationPanelViewController,
- new ShadeExpansionStateManager(),
- mNotificationStackScrollLayoutController,
- mStatusBarKeyguardViewManager,
- mStatusBarWindowStateController,
- mLockIconViewController,
- mCentralSurfaces,
- mNotificationShadeWindowController,
- mKeyguardUnlockAnimationController,
- mNotificationInsetsController,
- mAmbientState,
- mPulsingGestureListener,
- mKeyguardBouncerViewModel,
- mKeyguardBouncerComponentFactory,
- mAlternateBouncerInteractor,
- mUdfpsOverlayInteractor,
- mKeyguardTransitionInteractor,
- mPrimaryBouncerToGoneTransitionViewModel,
- featureFlags
- );
- mController.setupExpandedStatusBar();
- mController.setDragDownHelper(mDragDownHelper);
- }
-
- @Test
- public void testDragDownHelperCalledWhenDraggingDown() {
- when(mDragDownHelper.isDraggingDown()).thenReturn(true);
- long now = SystemClock.elapsedRealtime();
- MotionEvent ev = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0 /* x */, 0 /* y */,
- 0 /* meta */);
- mView.onTouchEvent(ev);
- verify(mDragDownHelper).onTouchEvent(ev);
- ev.recycle();
- }
-
- @Test
- public void testInterceptTouchWhenShowingAltAuth() {
- captureInteractionEventHandler();
-
- // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
- when(mStatusBarStateController.isDozing()).thenReturn(false);
- when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
- when(mUdfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(any())).thenReturn(true);
- when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
-
- // THEN we should intercept touch
- assertTrue(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
- }
-
- @Test
- public void testNoInterceptTouch() {
- captureInteractionEventHandler();
-
- // WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
- when(mStatusBarStateController.isDozing()).thenReturn(false);
- when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
- when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
-
- // THEN we shouldn't intercept touch
- assertFalse(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
- }
-
- @Test
- public void testHandleTouchEventWhenShowingAltAuth() {
- captureInteractionEventHandler();
-
- // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
- when(mStatusBarStateController.isDozing()).thenReturn(false);
- when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
- when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
-
- // THEN we should handle the touch
- assertTrue(mInteractionEventHandler.handleTouchEvent(mock(MotionEvent.class)));
- }
-
- private void captureInteractionEventHandler() {
- verify(mView).setInteractionEventHandler(mInteractionEventHandlerCaptor.capture());
- mInteractionEventHandler = mInteractionEventHandlerCaptor.getValue();
-
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
new file mode 100644
index 0000000..5d0f408
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shade
+
+import android.os.SystemClock
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.MotionEvent
+import android.widget.FrameLayout
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityContainerController
+import com.android.keyguard.LockIconViewController
+import com.android.keyguard.dagger.KeyguardBouncerComponent
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
+import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.dock.DockManager
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.data.repository.MultiShadeRepository
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
+import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
+import com.android.systemui.statusbar.DragDownHelper
+import com.android.systemui.statusbar.LockscreenShadeTransitionController
+import com.android.systemui.statusbar.NotificationInsetsController
+import com.android.systemui.statusbar.NotificationShadeDepthController
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.stack.AmbientState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.systemui.statusbar.window.StatusBarWindowStateController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class NotificationShadeWindowViewTest : SysuiTestCase() {
+
+ @Mock private lateinit var dragDownHelper: DragDownHelper
+ @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+ @Mock private lateinit var shadeController: ShadeController
+ @Mock private lateinit var centralSurfaces: CentralSurfaces
+ @Mock private lateinit var dockManager: DockManager
+ @Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
+ @Mock private lateinit var notificationStackScrollLayout: NotificationStackScrollLayout
+ @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
+ @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+ @Mock
+ private lateinit var notificationStackScrollLayoutController:
+ NotificationStackScrollLayoutController
+ @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
+ @Mock
+ private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
+ @Mock private lateinit var lockIconViewController: LockIconViewController
+ @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
+ @Mock private lateinit var ambientState: AmbientState
+ @Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+ @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
+ @Mock private lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
+ @Mock private lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
+ @Mock
+ private lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
+ @Mock private lateinit var notificationInsetsController: NotificationInsetsController
+ @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+ @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ @Mock
+ private lateinit var primaryBouncerToGoneTransitionViewModel:
+ PrimaryBouncerToGoneTransitionViewModel
+ @Captor
+ private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
+ @Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
+
+ private lateinit var underTest: NotificationShadeWindowView
+ private lateinit var controller: NotificationShadeWindowViewController
+ private lateinit var interactionEventHandler: InteractionEventHandler
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ underTest = spy(NotificationShadeWindowView(context, null))
+ whenever(
+ underTest.findViewById<NotificationStackScrollLayout>(
+ R.id.notification_stack_scroller
+ )
+ )
+ .thenReturn(notificationStackScrollLayout)
+ whenever(underTest.findViewById<FrameLayout>(R.id.keyguard_bouncer_container))
+ .thenReturn(mock())
+ whenever(keyguardBouncerComponentFactory.create(any())).thenReturn(keyguardBouncerComponent)
+ whenever(keyguardBouncerComponent.securityContainerController)
+ .thenReturn(keyguardSecurityContainerController)
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+ mDependency.injectTestDependency(ShadeController::class.java, shadeController)
+ whenever(dockManager.isDocked).thenReturn(false)
+ whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+ .thenReturn(emptyFlow())
+
+ val featureFlags = FakeFeatureFlags()
+ featureFlags.set(Flags.TRACKPAD_GESTURE_BACK, false)
+ featureFlags.set(Flags.DUAL_SHADE, false)
+ val inputProxy = MultiShadeInputProxy()
+ testScope = TestScope()
+ controller =
+ NotificationShadeWindowViewController(
+ lockscreenShadeTransitionController,
+ FalsingCollectorFake(),
+ statusBarStateController,
+ dockManager,
+ notificationShadeDepthController,
+ underTest,
+ notificationPanelViewController,
+ ShadeExpansionStateManager(),
+ notificationStackScrollLayoutController,
+ statusBarKeyguardViewManager,
+ statusBarWindowStateController,
+ lockIconViewController,
+ centralSurfaces,
+ notificationShadeWindowController,
+ keyguardUnlockAnimationController,
+ notificationInsetsController,
+ ambientState,
+ pulsingGestureListener,
+ keyguardBouncerViewModel,
+ keyguardBouncerComponentFactory,
+ alternateBouncerInteractor,
+ udfpsOverlayInteractor,
+ keyguardTransitionInteractor,
+ primaryBouncerToGoneTransitionViewModel,
+ featureFlags,
+ {
+ MultiShadeInteractor(
+ applicationScope = testScope.backgroundScope,
+ repository =
+ MultiShadeRepository(
+ applicationContext = context,
+ inputProxy = inputProxy,
+ ),
+ inputProxy = inputProxy,
+ )
+ },
+ FakeSystemClock(),
+ )
+
+ controller.setupExpandedStatusBar()
+ controller.setDragDownHelper(dragDownHelper)
+ }
+
+ @Test
+ fun testDragDownHelperCalledWhenDraggingDown() =
+ testScope.runTest {
+ whenever(dragDownHelper.isDraggingDown).thenReturn(true)
+ val now = SystemClock.elapsedRealtime()
+ val ev = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0f, 0f, 0 /* meta */)
+ underTest.onTouchEvent(ev)
+ verify(dragDownHelper).onTouchEvent(ev)
+ ev.recycle()
+ }
+
+ @Test
+ fun testInterceptTouchWhenShowingAltAuth() =
+ testScope.runTest {
+ captureInteractionEventHandler()
+
+ // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+ whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
+ whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(any())).thenReturn(true)
+ whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
+
+ // THEN we should intercept touch
+ assertThat(interactionEventHandler.shouldInterceptTouchEvent(mock())).isTrue()
+ }
+
+ @Test
+ fun testNoInterceptTouch() =
+ testScope.runTest {
+ captureInteractionEventHandler()
+
+ // WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+ whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(false)
+ whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
+
+ // THEN we shouldn't intercept touch
+ assertThat(interactionEventHandler.shouldInterceptTouchEvent(mock())).isFalse()
+ }
+
+ @Test
+ fun testHandleTouchEventWhenShowingAltAuth() =
+ testScope.runTest {
+ captureInteractionEventHandler()
+
+ // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+ whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
+ whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
+
+ // THEN we should handle the touch
+ assertThat(interactionEventHandler.handleTouchEvent(mock())).isTrue()
+ }
+
+ private fun captureInteractionEventHandler() {
+ verify(underTest).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
+ interactionEventHandler = interactionEventHandlerCaptor.value
+ }
+}