diff options
3 files changed, 69 insertions, 17 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt index ea2b3cdcf98c..605a5d261424 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt @@ -21,6 +21,7 @@ import android.platform.test.annotations.RequiresFlagsDisabled import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.CheckFlagsRule import android.platform.test.flag.junit.DeviceFlagsValueProvider +import android.view.IRemoteAnimationFinishedCallback import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -38,10 +39,13 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.anyInt +import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations import org.mockito.kotlin.any +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever @SmallTest @RunWith(AndroidJUnit4::class) @@ -222,4 +226,22 @@ class WindowManagerLockscreenVisibilityManagerTest : SysuiTestCase() { underTest.setSurfaceBehindVisibility(false) verify(keyguardTransitions).startKeyguardTransition(eq(true), any()) } + + @Test + fun remoteAnimationInstantlyFinished_ifDismissTransitionNotStarted() { + val mockedCallback = mock<IRemoteAnimationFinishedCallback>() + whenever(keyguardDismissTransitionInteractor.startDismissKeyguardTransition(any())) + .thenReturn(false) + + underTest.onKeyguardGoingAwayRemoteAnimationStart( + transit = 0, + apps = emptyArray(), + wallpapers = emptyArray(), + nonApps = emptyArray(), + finishedCallback = mockedCallback, + ) + + verify(mockedCallback).onAnimationFinished() + verifyNoMoreInteractions(mockedCallback) + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt index 5b28a3fa08de..a74384f61469 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt @@ -156,6 +156,13 @@ constructor( setWmLockscreenState(lockscreenShowing = lockscreenShown) } + /** + * Called when the keyguard going away remote animation is started, and we have a + * RemoteAnimationTarget to animate. + * + * This is triggered either by this class calling ATMS#keyguardGoingAway, or by WM directly, + * such as when an activity with FLAG_DISMISS_KEYGUARD is launched over a dismissible keyguard. + */ fun onKeyguardGoingAwayRemoteAnimationStart( @WindowManager.TransitionOldType transit: Int, apps: Array<RemoteAnimationTarget>, @@ -163,19 +170,32 @@ constructor( nonApps: Array<RemoteAnimationTarget>, finishedCallback: IRemoteAnimationFinishedCallback, ) { - // Make sure this is true - we set it true when requesting keyguardGoingAway, but there are - // cases where WM starts this transition on its own. - isKeyguardGoingAway = true + // If we weren't expecting the keyguard to be going away, WM triggered this transition. + if (!isKeyguardGoingAway) { + // Since WM triggered this, we're likely not transitioning to GONE yet. See if we can + // start that transition. + val startedDismiss = + keyguardDismissTransitionInteractor.startDismissKeyguardTransition( + reason = "Going away remote animation started" + ) - // Ensure that we've started a dismiss keyguard transition. WindowManager can start the - // going away animation on its own, if an activity launches and then requests dismissing the - // keyguard. In this case, this is the first and only signal we'll receive to start - // a transition to GONE. This transition needs to start even if we're not provided an app - // animation target - it's possible the app is destroyed on creation, etc. but we'll still - // be unlocking. - keyguardDismissTransitionInteractor.startDismissKeyguardTransition( - reason = "Going away remote animation started" - ) + if (!startedDismiss) { + // If the transition wasn't started, we're already GONE. This can happen with timing + // issues, where the remote animation took a long time to start, and something else + // caused us to unlock in the meantime. Since we're already GONE, simply end the + // remote animatiom immediately. + Log.d( + TAG, + "onKeyguardGoingAwayRemoteAnimationStart: " + + "Dismiss transition was not started; we're already GONE. " + + "Ending remote animation.", + ) + finishedCallback.onAnimationFinished() + return + } + + isKeyguardGoingAway = true + } if (apps.isNotEmpty()) { goingAwayRemoteAnimationFinishedCallback = finishedCallback @@ -278,6 +298,6 @@ constructor( } companion object { - private val TAG = WindowManagerLockscreenVisibilityManager::class.java.simpleName + private val TAG = "WindowManagerLsVis" } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissTransitionInteractor.kt index 4793d95b121c..089e5dc42df3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissTransitionInteractor.kt @@ -48,9 +48,12 @@ constructor( * * This is called exclusively by sources that can authoritatively say we should be unlocked, * including KeyguardSecurityContainerController and WindowManager. + * + * Returns [false] if the transition was not started, because we're already GONE or we don't + * know how to dismiss keyguard from the current state. */ - fun startDismissKeyguardTransition(reason: String = "") { - if (SceneContainerFlag.isEnabled) return + fun startDismissKeyguardTransition(reason: String = ""): Boolean { + if (SceneContainerFlag.isEnabled) return false Log.d(TAG, "#startDismissKeyguardTransition(reason=$reason)") val startedState = if (transitionRaceCondition()) { @@ -65,13 +68,20 @@ constructor( AOD -> fromAodTransitionInteractor.dismissAod() DOZING -> fromDozingTransitionInteractor.dismissFromDozing() KeyguardState.OCCLUDED -> fromOccludedTransitionInteractor.dismissFromOccluded() - KeyguardState.GONE -> + KeyguardState.GONE -> { Log.i( TAG, "Already transitioning to GONE; ignoring startDismissKeyguardTransition.", ) - else -> Log.e(TAG, "We don't know how to dismiss keyguard from state $startedState.") + return false + } + else -> { + Log.e(TAG, "We don't know how to dismiss keyguard from state $startedState.") + return false + } } + + return true } companion object { |