Loading core/java/android/service/dreams/flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -150,3 +150,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "dream_overlay_started_fix" namespace: "systemui" description: "Guards fix for the lifetime of when the dream is considered started" bug: "432039567" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +86 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.service.dreams.Flags import android.service.dreams.Flags.FLAG_DREAM_OVERLAY_STARTED_FIX import android.service.dreams.IDreamOverlay import android.service.dreams.IDreamOverlayCallback import android.service.dreams.IDreamOverlayClient Loading @@ -40,7 +41,6 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.Flags.FLAG_DREAM_BIOMETRIC_PROMPT_FIXES import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2 import com.android.systemui.Flags.FLAG_SCENE_CONTAINER Loading Loading @@ -749,7 +749,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT) @DisableFlags(FLAG_SCENE_CONTAINER, FLAG_GLANCEABLE_HUB_V2) @kotlin.Throws(RemoteException::class) fun testTransitionToGlanceableHub() = Loading @@ -775,7 +775,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_SCENE_CONTAINER, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_SCENE_CONTAINER) @DisableFlags(FLAG_GLANCEABLE_HUB_V2) @kotlin.Throws(RemoteException::class) fun testTransitionToGlanceableHub_sceneContainer() = Loading Loading @@ -803,7 +803,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_GLANCEABLE_HUB_V2) @Throws(RemoteException::class) fun testRedirect_v2Enabled_notTriggered() = kosmos.runTest { Loading @@ -823,7 +823,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT) @DisableFlags(FLAG_GLANCEABLE_HUB_V2) @Throws(RemoteException::class) fun testRedirectExit() = Loading Loading @@ -1410,6 +1410,86 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @EnableFlags(FLAG_DREAM_OVERLAY_STARTED_FIX) @Test fun testGestureBlocking_dreamEnded_gestureBlockingNotUpdated() = kosmos.runTest { val client = client // Inform the overlay service of dream starting. Do not show dream complications. client.startDream( mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*isPreview*/, false, /*shouldShowComplication*/ ) mMainExecutor.runAllReady() val callbackCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>() verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture()) // Gesture are blocked to start. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Trigger dream end, but delay the reset. whenever(mStateController.areExitAnimationsRunning()).thenReturn(true) client.endDream() mMainExecutor.runAllReady() // Shade is shown. callbackCaptor.firstValue.onShadeExpandedChanged(true) mMainExecutor.runAllReady() // Gesture blocking not updated since dream is already ended. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Finish exit animations, end dream. whenever(mStateController.areExitAnimationsRunning()).thenReturn(false) val stateCallbackCaptor = argumentCaptor<DreamOverlayStateController.Callback>() verify(mStateController).addCallback(stateCallbackCaptor.capture()) stateCallbackCaptor.lastValue.onStateChanged() mMainExecutor.runAllReady() // Gesture blocking removed on dream end. assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @DisableFlags(FLAG_DREAM_OVERLAY_STARTED_FIX) @Test fun testGestureBlocking_dreamEnded_gestureBlockingUpdated() = kosmos.runTest { val client = client // Inform the overlay service of dream starting. Do not show dream complications. client.startDream( mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*isPreview*/, false, /*shouldShowComplication*/ ) mMainExecutor.runAllReady() val callbackCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>() verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture()) // Gesture are blocked to start. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Trigger dream end, but delay the reset. whenever(mStateController.areExitAnimationsRunning()).thenReturn(true) client.endDream() mMainExecutor.runAllReady() // Shade is shown. callbackCaptor.firstValue.onShadeExpandedChanged(true) mMainExecutor.runAllReady() // Gesture blocking is still updated as the reset has not happened yet. assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @EnableFlags(FLAG_DREAM_BIOMETRIC_PROMPT_FIXES) @Test fun testBiometricPromptShowing_setsLifecycleState() = Loading Loading @@ -1575,8 +1655,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { @Parameters(name = "{0}") fun getParams(): List<FlagsParameterization> { return FlagsParameterization.allCombinationsOf( FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2, FLAG_DREAM_OVERLAY_STARTED_FIX, ) .andSceneContainer() } Loading packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +24 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.dreams; import static android.service.dreams.Flags.dreamOverlayStartedFix; import static android.service.dreams.Flags.dreamWakeRedirect; import static android.service.dreams.Flags.dreamsV2; Loading Loading @@ -134,9 +135,19 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ // A reference to the {@link Window} used to hold the dream overlay. private Window mWindow; // True if a dream has bound to the service and dream overlay service has started. /** * True if a dream has bound to the service and dream overlay service has started. Does not * immediately flip to false in {@link #onEndDream()}, waits until the overlay service state is * reset. */ private boolean mStarted = false; /** * True if the connected dream has been ended from {@link #onEndDream()} and has not fully * started yet. */ private boolean mEnded = false; // True if the service has been destroyed. private boolean mDestroyed = false; Loading Loading @@ -602,6 +613,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayCallbackController.onStartDream(); mStarted = true; mEnded = false; mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback); Loading @@ -626,6 +638,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ @Override public void onEndDream() { if (dreamOverlayStartedFix()) { mEnded = true; } mResetHandler.reset("ending dream"); } Loading @@ -644,8 +659,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ } } /** * Update the back gesture blocking state. Should only be called from * {@link #dreamScopedExecute(Runnable, String)}. */ private void updateGestureBlockingLocked() { final boolean shouldBlock = mStarted && !mShadeExpanded && !mBouncerShowing final boolean shouldBlock = (dreamOverlayStartedFix() || mStarted) && !mShadeExpanded && !mBouncerShowing && !isDreamInPreviewMode() && !mBiometricPromptShowing; if (shouldBlock) { Loading Loading @@ -809,7 +829,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private void dreamScopedExecute(Runnable runnable, String description) { mExecutor.execute(() -> { if (!mStarted) { if (!mStarted || mEnded) { Log.d(TAG, "could not execute when not dreaming:" + description); return; } Loading Loading
core/java/android/service/dreams/flags.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -150,3 +150,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "dream_overlay_started_fix" namespace: "systemui" description: "Guards fix for the lifetime of when the dream is considered started" bug: "432039567" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file
packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +86 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.service.dreams.Flags import android.service.dreams.Flags.FLAG_DREAM_OVERLAY_STARTED_FIX import android.service.dreams.IDreamOverlay import android.service.dreams.IDreamOverlayCallback import android.service.dreams.IDreamOverlayClient Loading @@ -40,7 +41,6 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.internal.logging.UiEventLogger import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.Flags.FLAG_DREAM_BIOMETRIC_PROMPT_FIXES import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2 import com.android.systemui.Flags.FLAG_SCENE_CONTAINER Loading Loading @@ -749,7 +749,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT) @DisableFlags(FLAG_SCENE_CONTAINER, FLAG_GLANCEABLE_HUB_V2) @kotlin.Throws(RemoteException::class) fun testTransitionToGlanceableHub() = Loading @@ -775,7 +775,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_SCENE_CONTAINER, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_SCENE_CONTAINER) @DisableFlags(FLAG_GLANCEABLE_HUB_V2) @kotlin.Throws(RemoteException::class) fun testTransitionToGlanceableHub_sceneContainer() = Loading Loading @@ -803,7 +803,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_GLANCEABLE_HUB_V2) @Throws(RemoteException::class) fun testRedirect_v2Enabled_notTriggered() = kosmos.runTest { Loading @@ -823,7 +823,7 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { } @Test @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT, FLAG_COMMUNAL_HUB) @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT) @DisableFlags(FLAG_GLANCEABLE_HUB_V2) @Throws(RemoteException::class) fun testRedirectExit() = Loading Loading @@ -1410,6 +1410,86 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @EnableFlags(FLAG_DREAM_OVERLAY_STARTED_FIX) @Test fun testGestureBlocking_dreamEnded_gestureBlockingNotUpdated() = kosmos.runTest { val client = client // Inform the overlay service of dream starting. Do not show dream complications. client.startDream( mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*isPreview*/, false, /*shouldShowComplication*/ ) mMainExecutor.runAllReady() val callbackCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>() verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture()) // Gesture are blocked to start. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Trigger dream end, but delay the reset. whenever(mStateController.areExitAnimationsRunning()).thenReturn(true) client.endDream() mMainExecutor.runAllReady() // Shade is shown. callbackCaptor.firstValue.onShadeExpandedChanged(true) mMainExecutor.runAllReady() // Gesture blocking not updated since dream is already ended. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Finish exit animations, end dream. whenever(mStateController.areExitAnimationsRunning()).thenReturn(false) val stateCallbackCaptor = argumentCaptor<DreamOverlayStateController.Callback>() verify(mStateController).addCallback(stateCallbackCaptor.capture()) stateCallbackCaptor.lastValue.onStateChanged() mMainExecutor.runAllReady() // Gesture blocking removed on dream end. assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @DisableFlags(FLAG_DREAM_OVERLAY_STARTED_FIX) @Test fun testGestureBlocking_dreamEnded_gestureBlockingUpdated() = kosmos.runTest { val client = client // Inform the overlay service of dream starting. Do not show dream complications. client.startDream( mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT, false /*isPreview*/, false, /*shouldShowComplication*/ ) mMainExecutor.runAllReady() val callbackCaptor = argumentCaptor<KeyguardUpdateMonitorCallback>() verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture()) // Gesture are blocked to start. assertThat(gestureRepository.gestureBlockedMatchers.value).hasSize(1) // Trigger dream end, but delay the reset. whenever(mStateController.areExitAnimationsRunning()).thenReturn(true) client.endDream() mMainExecutor.runAllReady() // Shade is shown. callbackCaptor.firstValue.onShadeExpandedChanged(true) mMainExecutor.runAllReady() // Gesture blocking is still updated as the reset has not happened yet. assertThat(gestureRepository.gestureBlockedMatchers.value).isEmpty() } @EnableFlags(FLAG_DREAM_BIOMETRIC_PROMPT_FIXES) @Test fun testBiometricPromptShowing_setsLifecycleState() = Loading Loading @@ -1575,8 +1655,8 @@ class DreamOverlayServiceTest(flags: FlagsParameterization?) : SysuiTestCase() { @Parameters(name = "{0}") fun getParams(): List<FlagsParameterization> { return FlagsParameterization.allCombinationsOf( FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2, FLAG_DREAM_OVERLAY_STARTED_FIX, ) .andSceneContainer() } Loading
packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +24 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.dreams; import static android.service.dreams.Flags.dreamOverlayStartedFix; import static android.service.dreams.Flags.dreamWakeRedirect; import static android.service.dreams.Flags.dreamsV2; Loading Loading @@ -134,9 +135,19 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ // A reference to the {@link Window} used to hold the dream overlay. private Window mWindow; // True if a dream has bound to the service and dream overlay service has started. /** * True if a dream has bound to the service and dream overlay service has started. Does not * immediately flip to false in {@link #onEndDream()}, waits until the overlay service state is * reset. */ private boolean mStarted = false; /** * True if the connected dream has been ended from {@link #onEndDream()} and has not fully * started yet. */ private boolean mEnded = false; // True if the service has been destroyed. private boolean mDestroyed = false; Loading Loading @@ -602,6 +613,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mDreamOverlayCallbackController.onStartDream(); mStarted = true; mEnded = false; mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback); Loading @@ -626,6 +638,9 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ @Override public void onEndDream() { if (dreamOverlayStartedFix()) { mEnded = true; } mResetHandler.reset("ending dream"); } Loading @@ -644,8 +659,13 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ } } /** * Update the back gesture blocking state. Should only be called from * {@link #dreamScopedExecute(Runnable, String)}. */ private void updateGestureBlockingLocked() { final boolean shouldBlock = mStarted && !mShadeExpanded && !mBouncerShowing final boolean shouldBlock = (dreamOverlayStartedFix() || mStarted) && !mShadeExpanded && !mBouncerShowing && !isDreamInPreviewMode() && !mBiometricPromptShowing; if (shouldBlock) { Loading Loading @@ -809,7 +829,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private void dreamScopedExecute(Runnable runnable, String description) { mExecutor.execute(() -> { if (!mStarted) { if (!mStarted || mEnded) { Log.d(TAG, "could not execute when not dreaming:" + description); return; } Loading