Loading packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +11 −0 Original line number Diff line number Diff line Loading @@ -33,12 +33,14 @@ import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransition import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf import com.android.systemui.util.kotlin.FlowDumperImpl import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @SysUISingleton Loading Loading @@ -106,4 +108,13 @@ constructor( step.transitionState == TransitionState.FINISHED || step.transitionState == TransitionState.CANCELED } val transitioningFromOrToDream = anyOf( keyguardTransitionInteractor.startedKeyguardTransitionStep.map { step -> step.to == DREAMING }, keyguardTransitionInteractor.isInTransition(Edge.create(from = DREAMING)), ) .distinctUntilChanged() } packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +31 −13 Original line number Diff line number Diff line Loading @@ -1352,7 +1352,6 @@ public class KeyguardViewMediator implements CoreStartable, && apps[0].taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_DREAM); final View localView = mKeyguardViewControllerLazy.get() .getViewRootImpl().getView(); final SyncRtSurfaceTransactionApplier applier = Loading @@ -1364,6 +1363,7 @@ public class KeyguardViewMediator implements CoreStartable, } if (isDream || mShowCommunalWhenUnoccluding) { Log.d(TAG, "Start unocclude animation for dream."); initAlphaForAnimationTargets(wallpapers); if (isDream) { mDreamViewModel.get().startTransitionFromDream(); Loading @@ -1371,6 +1371,11 @@ public class KeyguardViewMediator implements CoreStartable, mCommunalTransitionViewModel.get().snapToCommunal(); } mUnoccludeFinishedCallback = finishedCallback; if (!mIsKeyguardStateRelevantToDream) { // If this is triggered later than the dream-exit transition is // complete, make sure to finish. finishUnoccludeAnimation(); } return; } Loading Loading @@ -1453,8 +1458,16 @@ public class KeyguardViewMediator implements CoreStartable, }; } private Consumer<TransitionStep> getFinishedCallbackConsumerForDream() { mIsKeyguardStateRelevantToDream = false; return getFinishedCallbackConsumer(); } private Consumer<TransitionStep> getFinishedCallbackConsumer() { return (TransitionStep step) -> { return (TransitionStep step) -> finishUnoccludeAnimation(); } private void finishUnoccludeAnimation() { if (mUnoccludeFinishedCallback == null) return; try { mUnoccludeFinishedCallback.onAnimationFinished(); Loading @@ -1463,7 +1476,6 @@ public class KeyguardViewMediator implements CoreStartable, Log.e(TAG, "Wasn't able to callback", e); } mInteractionJankMonitor.end(CUJ_LOCKSCREEN_OCCLUSION); }; } private DeviceConfigProxy mDeviceConfig; Loading Loading @@ -1507,7 +1519,11 @@ public class KeyguardViewMediator implements CoreStartable, */ private RemoteAnimationTarget mOccludingRemoteAnimationTarget; private boolean mShowCommunalWhenUnoccluding = false; /** * Either transitioning to dreaming, from dreaming, or currently in the dreaming state. If the * transition away from dreaming ended, it's no longer relevant. */ private boolean mIsKeyguardStateRelevantToDream = false; private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager; private WindowManagerOcclusionManager mWmOcclusionManager; Loading Loading @@ -1780,7 +1796,9 @@ public class KeyguardViewMediator implements CoreStartable, mJavaAdapter.alwaysCollectFlow(dreamViewModel.getDreamAlpha(), getRemoteSurfaceAlphaApplier()); mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(), getFinishedCallbackConsumer()); getFinishedCallbackConsumerForDream()); mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitioningFromOrToDream(), (relevantToDream) -> mIsKeyguardStateRelevantToDream = relevantToDream); mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowCommunalFromOccluded(), (showCommunalFromOccluded) -> { mShowCommunalWhenUnoccluding = showCommunalFromOccluded; Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -251,6 +251,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { .thenReturn(mock(Flow.class)); when(mDreamViewModel.getTransitionEnded()) .thenReturn(mock(Flow.class)); when(mDreamViewModel.getTransitioningFromOrToDream()) .thenReturn(mock(Flow.class)); when(mCommunalTransitionViewModel.getShowCommunalFromOccluded()) .thenReturn(mock(Flow.class)); when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded()) Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTestKt.kt +71 −0 Original line number Diff line number Diff line Loading @@ -16,14 +16,25 @@ package com.android.systemui.keyguard import android.app.ActivityManager.RunningTaskInfo import android.app.IActivityTaskManager import android.app.WindowConfiguration import android.graphics.Point import android.graphics.Rect import android.internal.statusbar.statusBarService import android.os.Bundle import android.os.PowerManager import android.os.powerManager import android.platform.test.annotations.DisableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import android.view.IRemoteAnimationFinishedCallback import android.view.RemoteAnimationTarget import android.view.SurfaceControl import android.view.View import android.view.ViewRootImpl import android.view.WindowManager import androidx.test.filters.SmallTest import com.android.internal.logging.uiEventLogger import com.android.internal.widget.lockPatternUtils Loading @@ -31,6 +42,7 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.keyguardUnlockAnimationController import com.android.keyguard.mediator.ScreenOnCoordinator import com.android.keyguard.trustManager import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.activityTransitionAnimator import com.android.systemui.broadcast.broadcastDispatcher Loading @@ -53,8 +65,10 @@ import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.flags.systemPropertiesHelper import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionBootInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testDispatcher Loading Loading @@ -92,6 +106,7 @@ import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever /** Kotlin version of KeyguardViewMediatorTest to allow for coroutine testing. */ @SmallTest Loading Loading @@ -170,6 +185,9 @@ class KeyguardViewMediatorTestKt : SysuiTestCase() { @Before fun setUp() { testableLooper = TestableLooper.get(this) val testViewRoot = mock<ViewRootImpl>() whenever(testViewRoot.view).thenReturn(mock<View>()) whenever(kosmos.statusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot) } @Test Loading Loading @@ -231,6 +249,59 @@ class KeyguardViewMediatorTestKt : SysuiTestCase() { assertThat(communalSceneRepository.currentScene.value).isEqualTo(CommunalScenes.Blank) } @Test @DisableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun unoccludeAnimation_callsFinishedCallback_whenStartedAfterFromDreamingTransitionFinished() = kosmos.runTest { underTest.onSystemReady() testableLooper.processAllMessages() // Keyguard transition finished from dreaming to AOD underTest.onDreamingStopped() underTest.setShowingLocked(true, "") underTest.setDozing(true) fakeKeyguardTransitionRepository.transitionTo(KeyguardState.DREAMING, KeyguardState.AOD) // Start an unocclude animation afterwards val taskInfo = RunningTaskInfo().apply { topActivityType = WindowConfiguration.ACTIVITY_TYPE_DREAM } val apps = arrayOf( RemoteAnimationTarget( 0, RemoteAnimationTarget.MODE_CLOSING, mock<SurfaceControl>(), false, Rect(), Rect(), 0, Point(), Rect(), Rect(), WindowConfiguration(), false, mock<SurfaceControl>(), Rect(), taskInfo, false, ) ) val finishedCallback = mock<IRemoteAnimationFinishedCallback>() underTest.unoccludeAnimationRunner.onAnimationStart( WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE, apps, arrayOf(), null, finishedCallback, ) testableLooper.processAllMessages() verify(finishedCallback).onAnimationFinished() assertThat(underTest.isShowingAndNotOccluded).isTrue() } private fun Kosmos.enableHubOnCharging() { communalSettingsInteractor.setSuppressionReasons(emptyList()) batteryRepository.fake.setDevicePluggedIn(true) Loading Loading
packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +11 −0 Original line number Diff line number Diff line Loading @@ -33,12 +33,14 @@ import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransition import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf import com.android.systemui.util.kotlin.FlowDumperImpl import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @SysUISingleton Loading Loading @@ -106,4 +108,13 @@ constructor( step.transitionState == TransitionState.FINISHED || step.transitionState == TransitionState.CANCELED } val transitioningFromOrToDream = anyOf( keyguardTransitionInteractor.startedKeyguardTransitionStep.map { step -> step.to == DREAMING }, keyguardTransitionInteractor.isInTransition(Edge.create(from = DREAMING)), ) .distinctUntilChanged() }
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +31 −13 Original line number Diff line number Diff line Loading @@ -1352,7 +1352,6 @@ public class KeyguardViewMediator implements CoreStartable, && apps[0].taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_DREAM); final View localView = mKeyguardViewControllerLazy.get() .getViewRootImpl().getView(); final SyncRtSurfaceTransactionApplier applier = Loading @@ -1364,6 +1363,7 @@ public class KeyguardViewMediator implements CoreStartable, } if (isDream || mShowCommunalWhenUnoccluding) { Log.d(TAG, "Start unocclude animation for dream."); initAlphaForAnimationTargets(wallpapers); if (isDream) { mDreamViewModel.get().startTransitionFromDream(); Loading @@ -1371,6 +1371,11 @@ public class KeyguardViewMediator implements CoreStartable, mCommunalTransitionViewModel.get().snapToCommunal(); } mUnoccludeFinishedCallback = finishedCallback; if (!mIsKeyguardStateRelevantToDream) { // If this is triggered later than the dream-exit transition is // complete, make sure to finish. finishUnoccludeAnimation(); } return; } Loading Loading @@ -1453,8 +1458,16 @@ public class KeyguardViewMediator implements CoreStartable, }; } private Consumer<TransitionStep> getFinishedCallbackConsumerForDream() { mIsKeyguardStateRelevantToDream = false; return getFinishedCallbackConsumer(); } private Consumer<TransitionStep> getFinishedCallbackConsumer() { return (TransitionStep step) -> { return (TransitionStep step) -> finishUnoccludeAnimation(); } private void finishUnoccludeAnimation() { if (mUnoccludeFinishedCallback == null) return; try { mUnoccludeFinishedCallback.onAnimationFinished(); Loading @@ -1463,7 +1476,6 @@ public class KeyguardViewMediator implements CoreStartable, Log.e(TAG, "Wasn't able to callback", e); } mInteractionJankMonitor.end(CUJ_LOCKSCREEN_OCCLUSION); }; } private DeviceConfigProxy mDeviceConfig; Loading Loading @@ -1507,7 +1519,11 @@ public class KeyguardViewMediator implements CoreStartable, */ private RemoteAnimationTarget mOccludingRemoteAnimationTarget; private boolean mShowCommunalWhenUnoccluding = false; /** * Either transitioning to dreaming, from dreaming, or currently in the dreaming state. If the * transition away from dreaming ended, it's no longer relevant. */ private boolean mIsKeyguardStateRelevantToDream = false; private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager; private WindowManagerOcclusionManager mWmOcclusionManager; Loading Loading @@ -1780,7 +1796,9 @@ public class KeyguardViewMediator implements CoreStartable, mJavaAdapter.alwaysCollectFlow(dreamViewModel.getDreamAlpha(), getRemoteSurfaceAlphaApplier()); mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(), getFinishedCallbackConsumer()); getFinishedCallbackConsumerForDream()); mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitioningFromOrToDream(), (relevantToDream) -> mIsKeyguardStateRelevantToDream = relevantToDream); mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowCommunalFromOccluded(), (showCommunalFromOccluded) -> { mShowCommunalWhenUnoccluding = showCommunalFromOccluded; Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -251,6 +251,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { .thenReturn(mock(Flow.class)); when(mDreamViewModel.getTransitionEnded()) .thenReturn(mock(Flow.class)); when(mDreamViewModel.getTransitioningFromOrToDream()) .thenReturn(mock(Flow.class)); when(mCommunalTransitionViewModel.getShowCommunalFromOccluded()) .thenReturn(mock(Flow.class)); when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded()) Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTestKt.kt +71 −0 Original line number Diff line number Diff line Loading @@ -16,14 +16,25 @@ package com.android.systemui.keyguard import android.app.ActivityManager.RunningTaskInfo import android.app.IActivityTaskManager import android.app.WindowConfiguration import android.graphics.Point import android.graphics.Rect import android.internal.statusbar.statusBarService import android.os.Bundle import android.os.PowerManager import android.os.powerManager import android.platform.test.annotations.DisableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import android.view.IRemoteAnimationFinishedCallback import android.view.RemoteAnimationTarget import android.view.SurfaceControl import android.view.View import android.view.ViewRootImpl import android.view.WindowManager import androidx.test.filters.SmallTest import com.android.internal.logging.uiEventLogger import com.android.internal.widget.lockPatternUtils Loading @@ -31,6 +42,7 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.keyguardUnlockAnimationController import com.android.keyguard.mediator.ScreenOnCoordinator import com.android.keyguard.trustManager import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.activityTransitionAnimator import com.android.systemui.broadcast.broadcastDispatcher Loading @@ -53,8 +65,10 @@ import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.flags.systemPropertiesHelper import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionBootInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testDispatcher Loading Loading @@ -92,6 +106,7 @@ import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever /** Kotlin version of KeyguardViewMediatorTest to allow for coroutine testing. */ @SmallTest Loading Loading @@ -170,6 +185,9 @@ class KeyguardViewMediatorTestKt : SysuiTestCase() { @Before fun setUp() { testableLooper = TestableLooper.get(this) val testViewRoot = mock<ViewRootImpl>() whenever(testViewRoot.view).thenReturn(mock<View>()) whenever(kosmos.statusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot) } @Test Loading Loading @@ -231,6 +249,59 @@ class KeyguardViewMediatorTestKt : SysuiTestCase() { assertThat(communalSceneRepository.currentScene.value).isEqualTo(CommunalScenes.Blank) } @Test @DisableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun unoccludeAnimation_callsFinishedCallback_whenStartedAfterFromDreamingTransitionFinished() = kosmos.runTest { underTest.onSystemReady() testableLooper.processAllMessages() // Keyguard transition finished from dreaming to AOD underTest.onDreamingStopped() underTest.setShowingLocked(true, "") underTest.setDozing(true) fakeKeyguardTransitionRepository.transitionTo(KeyguardState.DREAMING, KeyguardState.AOD) // Start an unocclude animation afterwards val taskInfo = RunningTaskInfo().apply { topActivityType = WindowConfiguration.ACTIVITY_TYPE_DREAM } val apps = arrayOf( RemoteAnimationTarget( 0, RemoteAnimationTarget.MODE_CLOSING, mock<SurfaceControl>(), false, Rect(), Rect(), 0, Point(), Rect(), Rect(), WindowConfiguration(), false, mock<SurfaceControl>(), Rect(), taskInfo, false, ) ) val finishedCallback = mock<IRemoteAnimationFinishedCallback>() underTest.unoccludeAnimationRunner.onAnimationStart( WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE, apps, arrayOf(), null, finishedCallback, ) testableLooper.processAllMessages() verify(finishedCallback).onAnimationFinished() assertThat(underTest.isShowingAndNotOccluded).isTrue() } private fun Kosmos.enableHubOnCharging() { communalSettingsInteractor.setSuppressionReasons(emptyList()) batteryRepository.fake.setDevicePluggedIn(true) Loading