Merge "Multi-shade foundation - integration (5/5)." into udc-dev am: 0003196b1a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21990414

Change-Id: Ie210f3c61afb88ced9c92ebd974857098bee4b41
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Ale Nijamkin
2023-03-16 01:46:58 +00:00
committed by Automerger Merge Worker
7 changed files with 517 additions and 333 deletions

View File

@@ -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" />

View File

@@ -110,6 +110,13 @@
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="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 <com.android.systemui.biometrics.AuthRippleView
android:id="@+id/auth_ripple" android:id="@+id/auth_ripple"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -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()
}
}
}
}

View File

@@ -23,7 +23,6 @@ import android.app.StatusBarManager;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.session.MediaSessionLegacyHelper; import android.media.session.MediaSessionLegacyHelper;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.InputDevice; import android.view.InputDevice;
@@ -31,6 +30,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewStub;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.AuthKeyguardMessageArea; import com.android.keyguard.AuthKeyguardMessageArea;
@@ -39,8 +39,10 @@ import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor; import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManager;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -49,6 +51,8 @@ import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder; import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel; import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel; 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.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationInsetsController; import com.android.systemui.statusbar.NotificationInsetsController;
@@ -63,11 +67,13 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider;
/** /**
* Controller for {@link NotificationShadeWindowView}. * Controller for {@link NotificationShadeWindowView}.
@@ -115,6 +121,7 @@ public class NotificationShadeWindowViewController {
mIsOcclusionTransitionRunning = mIsOcclusionTransitionRunning =
step.getTransitionState() == TransitionState.RUNNING; step.getTransitionState() == TransitionState.RUNNING;
}; };
private final SystemClock mClock;
@Inject @Inject
public NotificationShadeWindowViewController( public NotificationShadeWindowViewController(
@@ -142,7 +149,9 @@ public class NotificationShadeWindowViewController {
UdfpsOverlayInteractor udfpsOverlayInteractor, UdfpsOverlayInteractor udfpsOverlayInteractor,
KeyguardTransitionInteractor keyguardTransitionInteractor, KeyguardTransitionInteractor keyguardTransitionInteractor,
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel, PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
FeatureFlags featureFlags) { FeatureFlags featureFlags,
Provider<MultiShadeInteractor> multiShadeInteractorProvider,
SystemClock clock) {
mLockscreenShadeTransitionController = transitionController; mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector; mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController; mStatusBarStateController = statusBarStateController;
@@ -175,6 +184,16 @@ public class NotificationShadeWindowViewController {
collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(), collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
mLockscreenToDreamingTransition); 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 @@ public class NotificationShadeWindowViewController {
mLockIconViewController.onTouchEvent( mLockIconViewController.onTouchEvent(
ev, ev,
() -> mService.wakeUpIfDozing( () -> mService.wakeUpIfDozing(
SystemClock.uptimeMillis(), mClock.uptimeMillis(),
mView, mView,
"LOCK_ICON_TOUCH", "LOCK_ICON_TOUCH",
PowerManager.WAKE_REASON_GESTURE) PowerManager.WAKE_REASON_GESTURE)
@@ -453,7 +472,7 @@ public class NotificationShadeWindowViewController {
public void cancelCurrentTouch() { public void cancelCurrentTouch() {
if (mTouchActive) { if (mTouchActive) {
final long now = SystemClock.uptimeMillis(); final long now = mClock.uptimeMillis();
final MotionEvent event; final MotionEvent event;
if (mIsTrackpadGestureBackEnabled) { if (mIsTrackpadGestureBackEnabled) {
event = MotionEvent.obtain(mDownEvent); event = MotionEvent.obtain(mDownEvent);

View File

@@ -37,6 +37,9 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel 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.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.NotificationInsetsController import com.android.systemui.statusbar.NotificationInsetsController
@@ -50,8 +53,12 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.window.StatusBarWindowStateController import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -65,10 +72,12 @@ import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true) @RunWithLooper(setAsMainLooper = true)
class NotificationShadeWindowViewControllerTest : SysuiTestCase() { class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Mock private lateinit var view: NotificationShadeWindowView @Mock private lateinit var view: NotificationShadeWindowView
@Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
@Mock private lateinit var centralSurfaces: CentralSurfaces @Mock private lateinit var centralSurfaces: CentralSurfaces
@@ -102,6 +111,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
private lateinit var underTest: NotificationShadeWindowViewController private lateinit var underTest: NotificationShadeWindowViewController
private lateinit var testScope: TestScope
@Before @Before
fun setUp() { fun setUp() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
@@ -115,8 +126,12 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition) whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
.thenReturn(emptyFlow<TransitionStep>()) .thenReturn(emptyFlow<TransitionStep>())
val featureFlags = FakeFeatureFlags(); val featureFlags = FakeFeatureFlags()
featureFlags.set(Flags.TRACKPAD_GESTURE_BACK, false) featureFlags.set(Flags.TRACKPAD_GESTURE_BACK, false)
featureFlags.set(Flags.DUAL_SHADE, false)
val inputProxy = MultiShadeInputProxy()
testScope = TestScope()
underTest = underTest =
NotificationShadeWindowViewController( NotificationShadeWindowViewController(
lockscreenShadeTransitionController, lockscreenShadeTransitionController,
@@ -144,6 +159,18 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
keyguardTransitionInteractor, keyguardTransitionInteractor,
primaryBouncerToGoneTransitionViewModel, primaryBouncerToGoneTransitionViewModel,
featureFlags, featureFlags,
{
MultiShadeInteractor(
applicationScope = testScope.backgroundScope,
repository =
MultiShadeRepository(
applicationContext = context,
inputProxy = inputProxy,
),
inputProxy = inputProxy,
)
},
FakeSystemClock(),
) )
underTest.setupExpandedStatusBar() underTest.setupExpandedStatusBar()
@@ -156,16 +183,18 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
// tests need to be added to test the rest of handleDispatchTouchEvent. // tests need to be added to test the rest of handleDispatchTouchEvent.
@Test @Test
fun handleDispatchTouchEvent_nullStatusBarViewController_returnsFalse() { fun handleDispatchTouchEvent_nullStatusBarViewController_returnsFalse() =
testScope.runTest {
underTest.setStatusBarViewController(null) underTest.setStatusBarViewController(null)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv) val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
assertThat(returnVal).isFalse() assertThat(returnVal).isFalse()
} }
@Test @Test
fun handleDispatchTouchEvent_downTouchBelowView_sendsTouchToSb() { fun handleDispatchTouchEvent_downTouchBelowView_sendsTouchToSb() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
val ev = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0) val ev = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
whenever(phoneStatusBarViewController.sendTouchToView(ev)).thenReturn(true) whenever(phoneStatusBarViewController.sendTouchToView(ev)).thenReturn(true)
@@ -177,13 +206,15 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
} }
@Test @Test
fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() { fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
val downEvBelow = val downEvBelow =
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0) MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
interactionEventHandler.handleDispatchTouchEvent(downEvBelow) interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0) val nextEvent =
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true) whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent) val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
@@ -193,22 +224,24 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
} }
@Test @Test
fun handleDispatchTouchEvent_downAndPanelCollapsedAndInSbBoundAndSbWindowShow_sendsTouchToSb() { fun handleDispatchTouchEvent_downAndPanelCollapsedAndInSbBoundAndSbWindowShow_sendsTouchToSb() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true) whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true) whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat())) whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
.thenReturn(true) .thenReturn(true)
whenever(phoneStatusBarViewController.sendTouchToView(downEv)).thenReturn(true) whenever(phoneStatusBarViewController.sendTouchToView(DOWN_EVENT)).thenReturn(true)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv) val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
verify(phoneStatusBarViewController).sendTouchToView(downEv) verify(phoneStatusBarViewController).sendTouchToView(DOWN_EVENT)
assertThat(returnVal).isTrue() assertThat(returnVal).isTrue()
} }
@Test @Test
fun handleDispatchTouchEvent_panelNotCollapsed_returnsNull() { fun handleDispatchTouchEvent_panelNotCollapsed_returnsNull() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true) whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat())) whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
@@ -216,14 +249,15 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
// Item we're testing // Item we're testing
whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(false) whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(false)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv) val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
verify(phoneStatusBarViewController, never()).sendTouchToView(downEv) verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
assertThat(returnVal).isNull() assertThat(returnVal).isNull()
} }
@Test @Test
fun handleDispatchTouchEvent_touchNotInSbBounds_returnsNull() { fun handleDispatchTouchEvent_touchNotInSbBounds_returnsNull() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true) whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true) whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
@@ -231,14 +265,15 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat())) whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
.thenReturn(false) .thenReturn(false)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv) val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
verify(phoneStatusBarViewController, never()).sendTouchToView(downEv) verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
assertThat(returnVal).isNull() assertThat(returnVal).isNull()
} }
@Test @Test
fun handleDispatchTouchEvent_sbWindowNotShowing_noSendTouchToSbAndReturnsTrue() { fun handleDispatchTouchEvent_sbWindowNotShowing_noSendTouchToSbAndReturnsTrue() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true) whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat())) whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
@@ -246,14 +281,15 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
// Item we're testing // Item we're testing
whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(false) whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(false)
val returnVal = interactionEventHandler.handleDispatchTouchEvent(downEv) val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
verify(phoneStatusBarViewController, never()).sendTouchToView(downEv) verify(phoneStatusBarViewController, never()).sendTouchToView(DOWN_EVENT)
assertThat(returnVal).isTrue() assertThat(returnVal).isTrue()
} }
@Test @Test
fun handleDispatchTouchEvent_downEventSentToSbThenAnotherEvent_sendsTouchToSb() { fun handleDispatchTouchEvent_downEventSentToSbThenAnotherEvent_sendsTouchToSb() =
testScope.runTest {
underTest.setStatusBarViewController(phoneStatusBarViewController) underTest.setStatusBarViewController(phoneStatusBarViewController)
whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true) whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true) whenever(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
@@ -261,7 +297,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
.thenReturn(true) .thenReturn(true)
// Down event first // Down event first
interactionEventHandler.handleDispatchTouchEvent(downEv) interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
// Then another event // Then another event
val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0) val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
@@ -274,29 +310,35 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
} }
@Test @Test
fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() { fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() =
testScope.runTest {
// Down event within udfpsOverlay bounds while alternateBouncer is showing // Down event within udfpsOverlay bounds while alternateBouncer is showing
whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(downEv)).thenReturn(false) whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(DOWN_EVENT))
.thenReturn(false)
whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true) whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
// Then touch should not be intercepted // Then touch should not be intercepted
val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(downEv) val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
assertThat(shouldIntercept).isFalse() assertThat(shouldIntercept).isFalse()
} }
@Test @Test
fun testGetBouncerContainer() { fun testGetBouncerContainer() =
testScope.runTest {
Mockito.clearInvocations(view) Mockito.clearInvocations(view)
underTest.bouncerContainer underTest.bouncerContainer
verify(view).findViewById<ViewGroup>(R.id.keyguard_bouncer_container) verify(view).findViewById<ViewGroup>(R.id.keyguard_bouncer_container)
} }
@Test @Test
fun testGetKeyguardMessageArea() { fun testGetKeyguardMessageArea() =
testScope.runTest {
underTest.keyguardMessageArea underTest.keyguardMessageArea
verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area) verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area)
} }
}
private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) companion object {
private const val VIEW_BOTTOM = 100 private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
private const val VIEW_BOTTOM = 100
}
}

View File

@@ -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();
}
}

View File

@@ -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
}
}