Loading packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +29 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.NotifPanelEvents import com.android.systemui.statusbar.CrossFadeHelper import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState Loading Loading @@ -85,12 +86,21 @@ class MediaHierarchyManager @Inject constructor( private val bypassController: KeyguardBypassController, private val mediaCarouselController: MediaCarouselController, private val notifLockscreenUserManager: NotificationLockscreenUserManager, private val keyguardViewController: KeyguardViewController, private val dreamOverlayStateController: DreamOverlayStateController, configurationController: ConfigurationController, wakefulnessLifecycle: WakefulnessLifecycle, private val keyguardViewController: KeyguardViewController, private val dreamOverlayStateController: DreamOverlayStateController panelEventsEvents: NotifPanelEvents, ) { /** * Whether we "skip" QQS during panel expansion. * * This means that when expanding the panel we go directly to QS. Also when we are on QS and * start closing the panel, it fully collapses instead of going to QQS. */ private var skipQqsOnExpansion: Boolean = false /** * The root overlay of the hierarchy. This is where the media notification is attached to * whenever the view is transitioning from one host to another. It also make sure that the Loading Loading @@ -504,6 +514,13 @@ class MediaHierarchyManager @Inject constructor( mediaCarouselController.updateUserVisibility = { mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() } panelEventsEvents.registerListener(object : NotifPanelEvents.Listener { override fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) { skipQqsOnExpansion = isExpandImmediateEnabled updateDesiredLocation() } }) } private fun updateConfiguration() { Loading Loading @@ -701,6 +718,9 @@ class MediaHierarchyManager @Inject constructor( if (isCurrentlyInGuidedTransformation()) { return false } if (skipQqsOnExpansion) { return false } // This is an invalid transition, and can happen when using the camera gesture from the // lock screen. Disallow. if (previousLocation == LOCATION_LOCKSCREEN && Loading Loading @@ -852,6 +872,9 @@ class MediaHierarchyManager @Inject constructor( * otherwise */ private fun getTransformationProgress(): Float { if (skipQqsOnExpansion) { return -1.0f } val progress = getQSTransformationProgress() if (statusbarState != StatusBarState.KEYGUARD && progress >= 0) { return progress Loading Loading @@ -1042,6 +1065,10 @@ class MediaHierarchyManager @Inject constructor( // reattach it without an animation return LOCATION_LOCKSCREEN } if (skipQqsOnExpansion) { // When doing an immediate expand or collapse, we want to keep it in QS. return LOCATION_QS } return location } Loading packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt +16 −2 Original line number Diff line number Diff line Loading @@ -29,11 +29,25 @@ interface NotifPanelEvents { interface Listener { /** Invoked when the notification panel starts or stops collapsing. */ fun onPanelCollapsingChanged(isCollapsing: Boolean) @JvmDefault fun onPanelCollapsingChanged(isCollapsing: Boolean) {} /** * Invoked when the notification panel starts or stops launching an [android.app.Activity]. */ fun onLaunchingActivityChanged(isLaunchingActivity: Boolean) @JvmDefault fun onLaunchingActivityChanged(isLaunchingActivity: Boolean) {} /** * Invoked when the "expand immediate" attribute changes. * * An example of expanding immediately is when swiping down from the top with two fingers. * Instead of going to QQS, we immediately expand to full QS. * * Another example is when full QS is showing, and we swipe up from the bottom. Instead of * going to QQS, the panel fully collapses. */ @JvmDefault fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) {} } } packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +17 −6 Original line number Diff line number Diff line Loading @@ -1745,12 +1745,17 @@ public final class NotificationPanelViewController extends PanelViewController { } if (mQsExpanded) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } super.collapse(delayed, speedUpFactor); } private void setQsExpandImmediate(boolean expandImmediate) { mQsExpandImmediate = expandImmediate; mPanelEventsEmitter.notifyExpandImmediateChange(expandImmediate); } private void setShowShelfOnly(boolean shelfOnly) { mNotificationStackScrollLayoutController.setShouldShowShelfOnly( shelfOnly && !mSplitShadeEnabled); Loading Loading @@ -1803,7 +1808,7 @@ public final class NotificationPanelViewController extends PanelViewController { public void expandWithQs() { if (isQsExpansionEnabled()) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } if (mSplitShadeEnabled && isOnKeyguard()) { Loading Loading @@ -2132,7 +2137,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) && event.getY(event.getActionIndex()) < mStatusBarMinHeight) { mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1); mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); requestPanelHeightUpdate(); Loading Loading @@ -3334,7 +3339,7 @@ public final class NotificationPanelViewController extends PanelViewController { } else { setListening(true); } mQsExpandImmediate = false; setQsExpandImmediate(false); setShowShelfOnly(false); mTwoFingerQsExpandPossible = false; updateTrackingHeadsUp(null); Loading Loading @@ -3392,7 +3397,7 @@ public final class NotificationPanelViewController extends PanelViewController { super.onTrackingStarted(); mScrimController.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } mNotificationStackScrollLayoutController.onPanelTrackingStarted(); Loading Loading @@ -4959,7 +4964,7 @@ public final class NotificationPanelViewController extends PanelViewController { // to locked will trigger this event and we're not actually in the process of opening // the shade, lockscreen is just always expanded if (mSplitShadeEnabled && !isOnKeyguard()) { mQsExpandImmediate = true; setQsExpandImmediate(true); } mCentralSurfaces.makeExpandedVisible(false); } Loading Loading @@ -5026,5 +5031,11 @@ public final class NotificationPanelViewController extends PanelViewController { cb.onPanelCollapsingChanged(isCollapsing); } } private void notifyExpandImmediateChange(boolean expandImmediateEnabled) { for (NotifPanelEvents.Listener cb : mListeners) { cb.onExpandImmediateChanged(expandImmediateEnabled); } } } } packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +52 −30 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.media import org.mockito.Mockito.`when` as whenever import android.graphics.Rect import android.testing.AndroidTestingRunner import android.testing.TestableLooper Loading @@ -30,6 +29,7 @@ import com.android.systemui.controls.controller.ControlsControllerImplTest.Compa import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.testing.FakeNotifPanelEvents import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController Loading @@ -50,10 +50,11 @@ import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyLong import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit @SmallTest Loading @@ -61,32 +62,19 @@ import org.mockito.junit.MockitoJUnit @TestableLooper.RunWithLooper class MediaHierarchyManagerTest : SysuiTestCase() { @Mock private lateinit var lockHost: MediaHost @Mock private lateinit var qsHost: MediaHost @Mock private lateinit var qqsHost: MediaHost @Mock private lateinit var bypassController: KeyguardBypassController @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var uniqueObjectHostView: UniqueObjectHostView @Mock private lateinit var dreamOverlayStateController: DreamOverlayStateController @Mock private lateinit var lockHost: MediaHost @Mock private lateinit var qsHost: MediaHost @Mock private lateinit var qqsHost: MediaHost @Mock private lateinit var bypassController: KeyguardBypassController @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var uniqueObjectHostView: UniqueObjectHostView @Mock private lateinit var dreamOverlayStateController: DreamOverlayStateController @Captor private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)> @Captor Loading @@ -97,6 +85,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var mediaHiearchyManager: MediaHierarchyManager private lateinit var mediaFrame: ViewGroup private val configurationController = FakeConfigurationController() private val notifPanelEvents = FakeNotifPanelEvents() @Before fun setup() { Loading @@ -111,10 +100,12 @@ class MediaHierarchyManagerTest : SysuiTestCase() { bypassController, mediaCarouselController, notificationLockscreenUserManager, keyguardViewController, dreamOverlayStateController, configurationController, wakefulnessLifecycle, keyguardViewController, dreamOverlayStateController) notifPanelEvents, ) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) Loading Loading @@ -211,6 +202,25 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) } @Test fun calculateTransformationType_notOnLockscreen_returnsTransition() { expandQS() val transformType = mediaHiearchyManager.calculateTransformationType() assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION) } @Test fun calculateTransformationType_onLockscreen_returnsTransition() { goToLockscreen() expandQS() val transformType = mediaHiearchyManager.calculateTransformationType() assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) } @Test fun calculateTransformationType_onLockShade_inSplitShade_goingToFullShade_returnsTransition() { enableSplitShade() Loading Loading @@ -294,6 +304,18 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isTrue() } @Test fun isCurrentlyInGuidedTransformation_hostsVisible_expandImmediateEnabled_returnsFalse() { notifPanelEvents.changeExpandImmediate(expandImmediate = true) goToLockscreen() enterGuidedTransformation() whenever(lockHost.visible).thenReturn(true) whenever(qsHost.visible).thenReturn(true) whenever(qqsHost.visible).thenReturn(true) assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isFalse() } @Test fun isCurrentlyInGuidedTransformation_hostNotVisible_returnsTrue() { goToLockscreen() Loading packages/SystemUI/tests/src/com/android/systemui/shade/testing/FakeNotifPanelEvents.kt 0 → 100644 +37 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.testing import com.android.systemui.shade.NotifPanelEvents /** Fake implementation of [NotifPanelEvents] for testing. */ class FakeNotifPanelEvents : NotifPanelEvents { private val listeners = mutableListOf<NotifPanelEvents.Listener>() override fun registerListener(listener: NotifPanelEvents.Listener) { listeners.add(listener) } override fun unregisterListener(listener: NotifPanelEvents.Listener) { listeners.remove(listener) } fun changeExpandImmediate(expandImmediate: Boolean) { listeners.forEach { it.onExpandImmediateChanged(expandImmediate) } } } Loading
packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +29 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.NotifPanelEvents import com.android.systemui.statusbar.CrossFadeHelper import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState Loading Loading @@ -85,12 +86,21 @@ class MediaHierarchyManager @Inject constructor( private val bypassController: KeyguardBypassController, private val mediaCarouselController: MediaCarouselController, private val notifLockscreenUserManager: NotificationLockscreenUserManager, private val keyguardViewController: KeyguardViewController, private val dreamOverlayStateController: DreamOverlayStateController, configurationController: ConfigurationController, wakefulnessLifecycle: WakefulnessLifecycle, private val keyguardViewController: KeyguardViewController, private val dreamOverlayStateController: DreamOverlayStateController panelEventsEvents: NotifPanelEvents, ) { /** * Whether we "skip" QQS during panel expansion. * * This means that when expanding the panel we go directly to QS. Also when we are on QS and * start closing the panel, it fully collapses instead of going to QQS. */ private var skipQqsOnExpansion: Boolean = false /** * The root overlay of the hierarchy. This is where the media notification is attached to * whenever the view is transitioning from one host to another. It also make sure that the Loading Loading @@ -504,6 +514,13 @@ class MediaHierarchyManager @Inject constructor( mediaCarouselController.updateUserVisibility = { mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser() } panelEventsEvents.registerListener(object : NotifPanelEvents.Listener { override fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) { skipQqsOnExpansion = isExpandImmediateEnabled updateDesiredLocation() } }) } private fun updateConfiguration() { Loading Loading @@ -701,6 +718,9 @@ class MediaHierarchyManager @Inject constructor( if (isCurrentlyInGuidedTransformation()) { return false } if (skipQqsOnExpansion) { return false } // This is an invalid transition, and can happen when using the camera gesture from the // lock screen. Disallow. if (previousLocation == LOCATION_LOCKSCREEN && Loading Loading @@ -852,6 +872,9 @@ class MediaHierarchyManager @Inject constructor( * otherwise */ private fun getTransformationProgress(): Float { if (skipQqsOnExpansion) { return -1.0f } val progress = getQSTransformationProgress() if (statusbarState != StatusBarState.KEYGUARD && progress >= 0) { return progress Loading Loading @@ -1042,6 +1065,10 @@ class MediaHierarchyManager @Inject constructor( // reattach it without an animation return LOCATION_LOCKSCREEN } if (skipQqsOnExpansion) { // When doing an immediate expand or collapse, we want to keep it in QS. return LOCATION_QS } return location } Loading
packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt +16 −2 Original line number Diff line number Diff line Loading @@ -29,11 +29,25 @@ interface NotifPanelEvents { interface Listener { /** Invoked when the notification panel starts or stops collapsing. */ fun onPanelCollapsingChanged(isCollapsing: Boolean) @JvmDefault fun onPanelCollapsingChanged(isCollapsing: Boolean) {} /** * Invoked when the notification panel starts or stops launching an [android.app.Activity]. */ fun onLaunchingActivityChanged(isLaunchingActivity: Boolean) @JvmDefault fun onLaunchingActivityChanged(isLaunchingActivity: Boolean) {} /** * Invoked when the "expand immediate" attribute changes. * * An example of expanding immediately is when swiping down from the top with two fingers. * Instead of going to QQS, we immediately expand to full QS. * * Another example is when full QS is showing, and we swipe up from the bottom. Instead of * going to QQS, the panel fully collapses. */ @JvmDefault fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) {} } }
packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +17 −6 Original line number Diff line number Diff line Loading @@ -1745,12 +1745,17 @@ public final class NotificationPanelViewController extends PanelViewController { } if (mQsExpanded) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } super.collapse(delayed, speedUpFactor); } private void setQsExpandImmediate(boolean expandImmediate) { mQsExpandImmediate = expandImmediate; mPanelEventsEmitter.notifyExpandImmediateChange(expandImmediate); } private void setShowShelfOnly(boolean shelfOnly) { mNotificationStackScrollLayoutController.setShouldShowShelfOnly( shelfOnly && !mSplitShadeEnabled); Loading Loading @@ -1803,7 +1808,7 @@ public final class NotificationPanelViewController extends PanelViewController { public void expandWithQs() { if (isQsExpansionEnabled()) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } if (mSplitShadeEnabled && isOnKeyguard()) { Loading Loading @@ -2132,7 +2137,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) && event.getY(event.getActionIndex()) < mStatusBarMinHeight) { mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1); mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); requestPanelHeightUpdate(); Loading Loading @@ -3334,7 +3339,7 @@ public final class NotificationPanelViewController extends PanelViewController { } else { setListening(true); } mQsExpandImmediate = false; setQsExpandImmediate(false); setShowShelfOnly(false); mTwoFingerQsExpandPossible = false; updateTrackingHeadsUp(null); Loading Loading @@ -3392,7 +3397,7 @@ public final class NotificationPanelViewController extends PanelViewController { super.onTrackingStarted(); mScrimController.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; setQsExpandImmediate(true); setShowShelfOnly(true); } mNotificationStackScrollLayoutController.onPanelTrackingStarted(); Loading Loading @@ -4959,7 +4964,7 @@ public final class NotificationPanelViewController extends PanelViewController { // to locked will trigger this event and we're not actually in the process of opening // the shade, lockscreen is just always expanded if (mSplitShadeEnabled && !isOnKeyguard()) { mQsExpandImmediate = true; setQsExpandImmediate(true); } mCentralSurfaces.makeExpandedVisible(false); } Loading Loading @@ -5026,5 +5031,11 @@ public final class NotificationPanelViewController extends PanelViewController { cb.onPanelCollapsingChanged(isCollapsing); } } private void notifyExpandImmediateChange(boolean expandImmediateEnabled) { for (NotifPanelEvents.Listener cb : mListeners) { cb.onExpandImmediateChanged(expandImmediateEnabled); } } } }
packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +52 −30 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.media import org.mockito.Mockito.`when` as whenever import android.graphics.Rect import android.testing.AndroidTestingRunner import android.testing.TestableLooper Loading @@ -30,6 +29,7 @@ import com.android.systemui.controls.controller.ControlsControllerImplTest.Compa import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.testing.FakeNotifPanelEvents import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController Loading @@ -50,10 +50,11 @@ import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyLong import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit @SmallTest Loading @@ -61,32 +62,19 @@ import org.mockito.junit.MockitoJUnit @TestableLooper.RunWithLooper class MediaHierarchyManagerTest : SysuiTestCase() { @Mock private lateinit var lockHost: MediaHost @Mock private lateinit var qsHost: MediaHost @Mock private lateinit var qqsHost: MediaHost @Mock private lateinit var bypassController: KeyguardBypassController @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var uniqueObjectHostView: UniqueObjectHostView @Mock private lateinit var dreamOverlayStateController: DreamOverlayStateController @Mock private lateinit var lockHost: MediaHost @Mock private lateinit var qsHost: MediaHost @Mock private lateinit var qqsHost: MediaHost @Mock private lateinit var bypassController: KeyguardBypassController @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var uniqueObjectHostView: UniqueObjectHostView @Mock private lateinit var dreamOverlayStateController: DreamOverlayStateController @Captor private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)> @Captor Loading @@ -97,6 +85,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var mediaHiearchyManager: MediaHierarchyManager private lateinit var mediaFrame: ViewGroup private val configurationController = FakeConfigurationController() private val notifPanelEvents = FakeNotifPanelEvents() @Before fun setup() { Loading @@ -111,10 +100,12 @@ class MediaHierarchyManagerTest : SysuiTestCase() { bypassController, mediaCarouselController, notificationLockscreenUserManager, keyguardViewController, dreamOverlayStateController, configurationController, wakefulnessLifecycle, keyguardViewController, dreamOverlayStateController) notifPanelEvents, ) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) Loading Loading @@ -211,6 +202,25 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) } @Test fun calculateTransformationType_notOnLockscreen_returnsTransition() { expandQS() val transformType = mediaHiearchyManager.calculateTransformationType() assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION) } @Test fun calculateTransformationType_onLockscreen_returnsTransition() { goToLockscreen() expandQS() val transformType = mediaHiearchyManager.calculateTransformationType() assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) } @Test fun calculateTransformationType_onLockShade_inSplitShade_goingToFullShade_returnsTransition() { enableSplitShade() Loading Loading @@ -294,6 +304,18 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isTrue() } @Test fun isCurrentlyInGuidedTransformation_hostsVisible_expandImmediateEnabled_returnsFalse() { notifPanelEvents.changeExpandImmediate(expandImmediate = true) goToLockscreen() enterGuidedTransformation() whenever(lockHost.visible).thenReturn(true) whenever(qsHost.visible).thenReturn(true) whenever(qqsHost.visible).thenReturn(true) assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isFalse() } @Test fun isCurrentlyInGuidedTransformation_hostNotVisible_returnsTrue() { goToLockscreen() Loading
packages/SystemUI/tests/src/com/android/systemui/shade/testing/FakeNotifPanelEvents.kt 0 → 100644 +37 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.testing import com.android.systemui.shade.NotifPanelEvents /** Fake implementation of [NotifPanelEvents] for testing. */ class FakeNotifPanelEvents : NotifPanelEvents { private val listeners = mutableListOf<NotifPanelEvents.Listener>() override fun registerListener(listener: NotifPanelEvents.Listener) { listeners.add(listener) } override fun unregisterListener(listener: NotifPanelEvents.Listener) { listeners.remove(listener) } fun changeExpandImmediate(expandImmediate: Boolean) { listeners.forEach { it.onExpandImmediateChanged(expandImmediate) } } }