diff options
| author | 2023-12-15 20:48:57 +0000 | |
|---|---|---|
| committer | 2023-12-15 20:48:57 +0000 | |
| commit | 2adc8deaad3e8e7017613f363264f52af83030b3 (patch) | |
| tree | c0e560668d12720a952518879988c4d1cd0d0f8d | |
| parent | 7f95d90fa6ab6c49c34b1b01ed1a1b4460e4ea9d (diff) | |
| parent | 5dd441575dac16080e3a0119080969ff90f4815a (diff) | |
Merge "Move glanceable hub container to the bottom of NotificationShadeWindowView" into main
7 files changed, 456 insertions, 44 deletions
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml index ca0fb85beb6e..87c31c8b8aae 100644 --- a/packages/SystemUI/res/layout/super_notification_shade.xml +++ b/packages/SystemUI/res/layout/super_notification_shade.xml @@ -26,6 +26,12 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> + <!-- Placeholder for the communal UI that will be replaced if the feature is enabled. --> + <ViewStub + android:id="@+id/communal_ui_stub" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + <com.android.systemui.scrim.ScrimView android:id="@+id/scrim_behind" android:layout_width="match_parent" @@ -64,12 +70,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> - <!-- Placeholder for the communal UI that will be replaced if the feature is enabled. --> - <ViewStub - android:id="@+id/communal_ui_stub" - android:layout_width="match_parent" - android:layout_height="match_parent" /> - <include layout="@layout/brightness_mirror_container" /> <com.android.systemui.scrim.ScrimView diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt index cae6147b03ee..f5bcab96a5a4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt @@ -80,6 +80,11 @@ enum class KeyguardState { return state != GONE } + /** Whether either of the bouncers are visible when we're FINISHED in the given state. */ + fun isBouncerState(state: KeyguardState): Boolean { + return state == PRIMARY_BOUNCER || state == ALTERNATE_BOUNCER + } + /** * Whether the device is awake ([PowerInteractor.isAwake]) when we're FINISHED in the given * keyguard state. @@ -107,4 +112,4 @@ enum class KeyguardState { return !deviceIsAwakeInState(state) } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt new file mode 100644 index 000000000000..ab69acbc6e9d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt @@ -0,0 +1,186 @@ +/* + * 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.shade + +import android.content.Context +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.View +import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +import com.android.systemui.compose.ComposeFacade.createCommunalContainer +import com.android.systemui.compose.ComposeFacade.isComposeAvailable +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.res.R +import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.util.kotlin.collectFlow +import javax.inject.Inject + +/** + * Controller that's responsible for the glanceable hub container view and its touch handling. + * + * This will be used until the glanceable hub is integrated into Flexiglass. + */ +class GlanceableHubContainerController +@Inject +constructor( + private val communalInteractor: CommunalInteractor, + private val communalViewModel: CommunalViewModel, + private val keyguardTransitionInteractor: KeyguardTransitionInteractor, + private val shadeInteractor: ShadeInteractor, +) { + /** The container view for the hub. This will not be initialized until [initView] is called. */ + private lateinit var communalContainerView: View + + /** + * The width of the area in which a right edge swipe can open the hub, in pixels. Read from + * resources when [initView] is called. + */ + private var edgeSwipeRegionWidth: Int = 0 + + /** + * True if we are currently tracking a gesture for opening the hub that started in the edge + * swipe region. + */ + private var isTrackingOpenGesture = false + + /** + * True if the hub UI is fully open, meaning it should receive touch input. + * + * Tracks [CommunalInteractor.isCommunalShowing]. + */ + private var hubShowing = false + + /** + * True if either the primary or alternate bouncer are open, meaning the hub should not receive + * any touch input. + * + * Tracks [KeyguardTransitionInteractor.isFinishedInState] for [KeyguardState.isBouncerState]. + */ + private var anyBouncerShowing = false + + /** + * True if the shade is fully expanded, meaning the hub should not receive any touch input. + * + * Tracks [ShadeInteractor.isAnyFullyExpanded]. + */ + private var shadeShowing = false + + /** Returns true if the glanceable hub is enabled and the container view can be created. */ + fun isEnabled(): Boolean { + return communalInteractor.isCommunalEnabled && isComposeAvailable() + } + + /** + * Creates the container view containing the glanceable hub UI. + * + * @throws RuntimeException if [isEnabled] is false or the view is already initialized + */ + fun initView( + context: Context, + ): View { + return initView(createCommunalContainer(context, communalViewModel)) + } + + /** Override for testing. */ + @VisibleForTesting + internal fun initView(containerView: View): View { + if (!isEnabled()) { + throw RuntimeException("Glanceable hub is not enabled") + } + if (::communalContainerView.isInitialized) { + throw RuntimeException("Communal view has already been initialized") + } + + communalContainerView = containerView + + edgeSwipeRegionWidth = + communalContainerView.resources.getDimensionPixelSize(R.dimen.communal_grid_gutter_size) + + collectFlow( + communalContainerView, + keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState), + { anyBouncerShowing = it } + ) + collectFlow( + communalContainerView, + communalInteractor.isCommunalShowing, + { hubShowing = it } + ) + collectFlow( + communalContainerView, + shadeInteractor.isAnyFullyExpanded, + { shadeShowing = it } + ) + + return communalContainerView + } + + /** + * Notifies the hub container of a touch event. Returns true if it's determined that the touch + * should go to the hub container and no one else. + * + * Special handling is needed because the hub container sits at the lowest z-order in + * [NotificationShadeWindowView] and would not normally receive touches. We also cannot use a + * [GestureDetector] as the hub container's SceneTransitionLayout is a Compose view that expects + * to be fully in control of its own touch handling. + */ + fun onTouchEvent(ev: MotionEvent): Boolean { + if (!::communalContainerView.isInitialized) { + return false + } + + val isDown = ev.actionMasked == MotionEvent.ACTION_DOWN + val isUp = ev.actionMasked == MotionEvent.ACTION_UP + val isCancel = ev.actionMasked == MotionEvent.ACTION_CANCEL + + // TODO(b/315207481): also account for opening animations of shade/bouncer and not just + // fully showing state + val hubOccluded = anyBouncerShowing || shadeShowing + + // If the hub is fully visible, send all touch events to it. + val communalVisible = hubShowing && !hubOccluded + if (communalVisible) { + return communalContainerView.dispatchTouchEvent(ev) + } + + if (edgeSwipeRegionWidth == 0) { + // If the edge region width has not been read yet or whatever reason, don't bother + // intercepting touches to open the hub. + return false + } + + if (!isTrackingOpenGesture && isDown) { + val x = ev.rawX + val inOpeningSwipeRegion: Boolean = + x >= communalContainerView.width - edgeSwipeRegionWidth + if (inOpeningSwipeRegion && !hubOccluded) { + isTrackingOpenGesture = true + return communalContainerView.dispatchTouchEvent(ev) + } + } else if (isTrackingOpenGesture) { + if (isUp || isCancel) { + isTrackingOpenGesture = false + } + return communalContainerView.dispatchTouchEvent(ev) + } + + return false + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 73537edcc94a..07ce57735dc7 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -42,9 +42,6 @@ import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder; import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel; import com.android.systemui.classifier.FalsingCollector; -import com.android.systemui.communal.data.repository.CommunalRepository; -import com.android.systemui.communal.ui.viewmodel.CommunalViewModel; -import com.android.systemui.compose.ComposeFacade; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; import com.android.systemui.dock.DockManager; @@ -108,14 +105,14 @@ public class NotificationShadeWindowViewController implements Dumpable { private final PulsingGestureListener mPulsingGestureListener; private final LockscreenHostedDreamGestureListener mLockscreenHostedDreamGestureListener; private final NotificationInsetsController mNotificationInsetsController; - private final CommunalViewModel mCommunalViewModel; - private final CommunalRepository mCommunalRepository; private final boolean mIsTrackpadCommonEnabled; private final FeatureFlagsClassic mFeatureFlagsClassic; private final SysUIKeyEventHandler mSysUIKeyEventHandler; private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; private final AlternateBouncerInteractor mAlternateBouncerInteractor; private final QuickSettingsController mQuickSettingsController; + private final GlanceableHubContainerController + mGlanceableHubContainerController; private GestureDetector mPulsingWakeupGestureHandler; private GestureDetector mDreamingWakeupGestureHandler; private View mBrightnessMirror; @@ -183,8 +180,7 @@ public class NotificationShadeWindowViewController implements Dumpable { KeyguardMessageAreaController.Factory messageAreaControllerFactory, KeyguardTransitionInteractor keyguardTransitionInteractor, PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel, - CommunalViewModel communalViewModel, - CommunalRepository communalRepository, + GlanceableHubContainerController glanceableHubContainerController, NotificationLaunchAnimationInteractor notificationLaunchAnimationInteractor, FeatureFlagsClassic featureFlagsClassic, SystemClock clock, @@ -217,8 +213,7 @@ public class NotificationShadeWindowViewController implements Dumpable { mPulsingGestureListener = pulsingGestureListener; mLockscreenHostedDreamGestureListener = lockscreenHostedDreamGestureListener; mNotificationInsetsController = notificationInsetsController; - mCommunalViewModel = communalViewModel; - mCommunalRepository = communalRepository; + mGlanceableHubContainerController = glanceableHubContainerController; mIsTrackpadCommonEnabled = featureFlagsClassic.isEnabled(TRACKPAD_GESTURE_COMMON); mFeatureFlagsClassic = featureFlagsClassic; mSysUIKeyEventHandler = sysUIKeyEventHandler; @@ -347,6 +342,10 @@ public class NotificationShadeWindowViewController implements Dumpable { mFalsingCollector.onTouchEvent(ev); mPulsingWakeupGestureHandler.onTouchEvent(ev); + + if (mGlanceableHubContainerController.onTouchEvent(ev)) { + return logDownDispatch(ev, "dispatched to glanceable hub container", true); + } if (mDreamingWakeupGestureHandler != null && mDreamingWakeupGestureHandler.onTouchEvent(ev)) { return logDownDispatch(ev, "dream wakeup gesture handled", true); @@ -587,14 +586,13 @@ public class NotificationShadeWindowViewController implements Dumpable { } /** - * Sets up the communal hub UI if the {@link com.android.systemui.Flags#FLAG_COMMUNAL_HUB} flag - * is enabled. + * Sets up the glanceable hub UI if the {@link com.android.systemui.Flags#FLAG_COMMUNAL_HUB} + * flag is enabled. * - * The layout lives in {@link R.id.communal_ui_container}. + * The layout lives in {@link R.id.communal_ui_stub}. */ public void setupCommunalHubLayout() { - if (!mCommunalRepository.isCommunalEnabled() - || !ComposeFacade.INSTANCE.isComposeAvailable()) { + if (!mGlanceableHubContainerController.isEnabled()) { return; } @@ -602,8 +600,8 @@ public class NotificationShadeWindowViewController implements Dumpable { View communalPlaceholder = mView.findViewById(R.id.communal_ui_stub); int index = mView.indexOfChild(communalPlaceholder); mView.removeView(communalPlaceholder); - mView.addView(ComposeFacade.INSTANCE.createCommunalContainer(mView.getContext(), - mCommunalViewModel), index); + + mView.addView(mGlanceableHubContainerController.initView(mView.getContext()), index); } private boolean didNotificationPanelInterceptEvent(MotionEvent ev) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt new file mode 100644 index 000000000000..5569ca9520e9 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt @@ -0,0 +1,220 @@ +/* + * 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.shade + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.testing.ViewUtils +import android.view.MotionEvent +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.data.repository.FakeCommunalRepository +import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.shared.model.CommunalSceneKey +import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor +import com.android.systemui.res.R +import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.MutableStateFlow +import org.junit.Assert.assertThrows +import org.junit.Assume.assumeTrue +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +class GlanceableHubContainerControllerTest : SysuiTestCase() { + @Mock private lateinit var communalViewModel: CommunalViewModel + @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor + @Mock private lateinit var shadeInteractor: ShadeInteractor + + private lateinit var containerView: View + private lateinit var testableLooper: TestableLooper + + private lateinit var communalInteractor: CommunalInteractor + private lateinit var communalRepository: FakeCommunalRepository + private lateinit var underTest: GlanceableHubContainerController + + private val bouncerShowingFlow = MutableStateFlow(false) + private val shadeShowingFlow = MutableStateFlow(false) + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + val withDeps = CommunalInteractorFactory.create() + communalInteractor = withDeps.communalInteractor + communalRepository = withDeps.communalRepository + + underTest = + GlanceableHubContainerController( + communalInteractor, + communalViewModel, + keyguardTransitionInteractor, + shadeInteractor + ) + testableLooper = TestableLooper.get(this) + + communalRepository.setIsCommunalEnabled(true) + + whenever(keyguardTransitionInteractor.isFinishedInStateWhere(any())) + .thenReturn(bouncerShowingFlow) + whenever(shadeInteractor.isAnyFullyExpanded).thenReturn(shadeShowingFlow) + + overrideResource(R.dimen.communal_grid_gutter_size, SWIPE_REGION_WIDTH) + } + + @Test + fun isEnabled_interactorEnabled_returnsTrue() { + communalRepository.setIsCommunalEnabled(true) + + assertThat(underTest.isEnabled()).isTrue() + } + + @Test + fun isEnabled_interactorDisabled_returnsFalse() { + communalRepository.setIsCommunalEnabled(false) + + assertThat(underTest.isEnabled()).isFalse() + } + + @Test + fun initView_notEnabled_throwsException() { + communalRepository.setIsCommunalEnabled(false) + + assertThrows(RuntimeException::class.java) { underTest.initView(context) } + } + + @Test + fun initView_calledTwice_throwsException() { + // First call succeeds. + underTest.initView(context) + + // Second call throws. + assertThrows(RuntimeException::class.java) { underTest.initView(context) } + } + + @Test + fun onTouchEvent_touchInsideGestureRegion_returnsTrue() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + // Touch events are intercepted. + assertThat(underTest.onTouchEvent(DOWN_IN_SWIPE_REGION_EVENT)).isTrue() + } + + @Test + fun onTouchEvent_subsequentTouchesAfterGestureStart_returnsTrue() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + // Initial touch down is intercepted, and so are touches outside of the region, until an up + // event is received. + assertThat(underTest.onTouchEvent(DOWN_IN_SWIPE_REGION_EVENT)).isTrue() + assertThat(underTest.onTouchEvent(MOVE_EVENT)).isTrue() + assertThat(underTest.onTouchEvent(UP_EVENT)).isTrue() + assertThat(underTest.onTouchEvent(MOVE_EVENT)).isFalse() + } + + @Test + fun onTouchEvent_communalOpen_returnsTrue() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + testableLooper.processAllMessages() + + // Touch events are intercepted. + assertThat(underTest.onTouchEvent(DOWN_EVENT)).isTrue() + } + + @Test + fun onTouchEvent_communalAndBouncerShowing_returnsFalse() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + // Bouncer is visible. + bouncerShowingFlow.value = true + testableLooper.processAllMessages() + + // Touch events are not intercepted. + assertThat(underTest.onTouchEvent(DOWN_EVENT)).isFalse() + } + + @Test + fun onTouchEvent_communalAndShadeShowing_returnsFalse() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + shadeShowingFlow.value = true + testableLooper.processAllMessages() + + // Touch events are not intercepted. + assertThat(underTest.onTouchEvent(DOWN_EVENT)).isFalse() + } + + private fun initAndAttachContainerView() { + containerView = View(context) + // Make view clickable so that dispatchTouchEvent returns true. + containerView.isClickable = true + + underTest.initView(containerView) + // Attach the view so that flows start collecting. + ViewUtils.attachView(containerView) + // Give the view a size so that determining if a touch starts at the right edge works. + containerView.layout(0, 0, CONTAINER_WIDTH, CONTAINER_HEIGHT) + } + + companion object { + private const val CONTAINER_WIDTH = 100 + private const val CONTAINER_HEIGHT = 100 + private const val SWIPE_REGION_WIDTH = 20 + + private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) + private val DOWN_IN_SWIPE_REGION_EVENT = + MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0) + private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0) + private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0) + + @BeforeClass + @JvmStatic + fun beforeClass() { + // Glanceable hub requires Compose, no point running any of these tests if compose isn't + // enabled. + assumeTrue(ComposeFacade.isComposeAvailable()) + } + } +} 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 6ff79660efec..9d997dae6836 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.shade +import android.content.Context import android.os.Handler import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper @@ -45,8 +46,6 @@ import com.android.systemui.bouncer.ui.BouncerView import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorFake -import com.android.systemui.communal.data.repository.FakeCommunalRepository -import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.compose.ComposeFacade.isComposeAvailable import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager @@ -98,6 +97,7 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.test.TestScope @@ -112,9 +112,8 @@ import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.util.Optional import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -150,8 +149,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock private lateinit var mLockscreenHostedDreamGestureListener: LockscreenHostedDreamGestureListener @Mock private lateinit var notificationInsetsController: NotificationInsetsController - @Mock private lateinit var mCommunalViewModel: CommunalViewModel - private lateinit var mCommunalRepository: FakeCommunalRepository + @Mock private lateinit var mGlanceableHubContainerController: GlanceableHubContainerController @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController @@ -201,8 +199,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { featureFlagsClassic.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false) mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) - mCommunalRepository = FakeCommunalRepository() - testScope = TestScope() fakeClock = FakeSystemClock() underTest = @@ -236,8 +232,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { mock(KeyguardMessageAreaController.Factory::class.java), keyguardTransitionInteractor, primaryBouncerToGoneTransitionViewModel, - mCommunalViewModel, - mCommunalRepository, + mGlanceableHubContainerController, notificationLaunchAnimationInteractor, featureFlagsClassic, fakeClock, @@ -466,6 +461,16 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { } @Test + fun handleDispatchTouchEvent_glanceableHubIntercepts_returnsTrue() { + whenever(mGlanceableHubContainerController.onTouchEvent(DOWN_EVENT)).thenReturn(true) + underTest.setStatusBarViewController(phoneStatusBarViewController) + + val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT) + + assertThat(returnVal).isTrue() + } + + @Test fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() { // down event should be intercepted by keyguardViewManager whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT)) @@ -546,7 +551,11 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { return } - mCommunalRepository.setIsCommunalEnabled(true) + whenever(mGlanceableHubContainerController.isEnabled()).thenReturn(true) + + val mockCommunalView = mock(View::class.java) + whenever(mGlanceableHubContainerController.initView(any<Context>())) + .thenReturn(mockCommunalView) val mockCommunalPlaceholder = mock(View::class.java) val fakeViewIndex = 20 @@ -558,7 +567,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { // Communal view added as a child of the container at the proper index, the stub is removed. verify(view).removeView(mockCommunalPlaceholder) - verify(view).addView(any(), eq(fakeViewIndex)) + verify(view).addView(eq(mockCommunalView), eq(fakeViewIndex)) } @Test @@ -567,7 +576,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { return } - mCommunalRepository.setIsCommunalEnabled(false) + whenever(mGlanceableHubContainerController.isEnabled()).thenReturn(false) val mockCommunalPlaceholder = mock(View::class.java) val fakeViewIndex = 20 diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt index 29b1366eb6c1..9750f60c7b19 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt @@ -41,8 +41,6 @@ import com.android.systemui.bouncer.ui.BouncerView import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorFake -import com.android.systemui.communal.data.repository.FakeCommunalRepository -import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.dump.logcatLogBuffer @@ -142,8 +140,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { private lateinit var unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider> @Mock private lateinit var notificationInsetsController: NotificationInsetsController - @Mock private lateinit var mCommunalViewModel: CommunalViewModel - private lateinit var mCommunalRepository: FakeCommunalRepository + @Mock private lateinit var mGlanceableHubContainerController: GlanceableHubContainerController @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor @@ -180,8 +177,6 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition) .thenReturn(emptyFlow()) - mCommunalRepository = FakeCommunalRepository() - val featureFlags = FakeFeatureFlags() featureFlags.set(Flags.TRACKPAD_GESTURE_COMMON, true) featureFlags.set(Flags.TRACKPAD_GESTURE_FEATURES, false) @@ -221,8 +216,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() { Mockito.mock(KeyguardMessageAreaController.Factory::class.java), keyguardTransitionInteractor, primaryBouncerToGoneTransitionViewModel, - mCommunalViewModel, - mCommunalRepository, + mGlanceableHubContainerController, NotificationLaunchAnimationInteractor(NotificationLaunchAnimationRepository()), featureFlags, FakeSystemClock(), |