Loading packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +18 −7 Original line number Diff line number Diff line Loading @@ -682,8 +682,11 @@ public class KeyguardViewMediator implements CoreStartable, Log.d(TAG, String.format("onBeforeUserSwitching %d", userId)); synchronized (KeyguardViewMediator.this) { mHandler.removeCallbacksAndMessages(mDismissToken); mHandler.removeMessages(START_KEYGUARD_EXIT_ANIM); mHandler.removeMessages(DISMISS); mHandler.removeMessages(HIDE); mIsKeyguardExitAnimationCanceled = true; notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); adjustStatusBarLocked(); Loading Loading @@ -3681,6 +3684,12 @@ public class KeyguardViewMediator implements CoreStartable, } } // Allows the runnable to be controlled for tests by overriding this method @VisibleForTesting void postAfterTraversal(Runnable runnable) { DejankUtils.postAfterTraversal(runnable); } /** * Called when we're done running the keyguard exit animation, we should now end up unlocked. * Loading @@ -3700,12 +3709,6 @@ public class KeyguardViewMediator implements CoreStartable, return; } if (mIsKeyguardExitAnimationCanceled) { Log.d(TAG, "Ignoring exitKeyguardAndFinishSurfaceBehindRemoteAnimation. " + "mIsKeyguardExitAnimationCanceled==true"); return; } // Block the panel from expanding, in case we were doing a swipe to dismiss gesture. mKeyguardViewControllerLazy.get().blockPanelExpansionFromCurrentTouch(); final boolean wasShowing = ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS Loading @@ -3713,7 +3716,7 @@ public class KeyguardViewMediator implements CoreStartable, InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION); // Post layout changes to the next frame, so we don't hang at the end of the animation. DejankUtils.postAfterTraversal(() -> { postAfterTraversal(() -> { if (!mPM.isInteractive() && !mPendingLock) { Log.e(TAG, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation#postAfterTraversal:" + " mPM.isInteractive()=" + mPM.isInteractive() Loading @@ -3728,6 +3731,14 @@ public class KeyguardViewMediator implements CoreStartable, return; } if (mIsKeyguardExitAnimationCanceled) { Log.d(TAG, "Ignoring exitKeyguardAndFinishSurfaceBehindRemoteAnimation. " + "mIsKeyguardExitAnimationCanceled==true"); finishSurfaceBehindRemoteAnimation(true /* showKeyguard */); setShowingLocked(true /* showing */, true /* force */, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation - canceled"); return; } onKeyguardExitFinished("exitKeyguardAndFinishSurfaceBehindRemoteAnimation"); Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +75 −2 Original line number Diff line number Diff line Loading @@ -234,12 +234,16 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private FakeFeatureFlags mFeatureFlags; private final int mDefaultUserId = 100; private boolean mUsePostAfterTraversalRunnable; private Runnable mPostAfterTraversalRunnable; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mFalsingCollector = new FalsingCollectorFake(); mSystemClock = new FakeSystemClock(); mUsePostAfterTraversalRunnable = false; mPostAfterTraversalRunnable = null; when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager); when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class)); when(mPowerManager.isInteractive()).thenReturn(true); Loading Loading @@ -307,7 +311,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { */ @After public void assertATMSAndKeyguardViewMediatorStatesMatch() { android.util.Log.i("CLJ", "7"); try { if (mKeyguardGoingAway) { assertATMSKeyguardGoingAway(); Loading Loading @@ -378,6 +381,10 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { null, callback); processAllMessagesAndBgExecutorMessages(); // Followed by a request to dismiss the keyguard completely, which needs to be rejected mViewMediator.mViewMediatorCallback.keyguardDonePending(mDefaultUserId); mViewMediator.mViewMediatorCallback.readyForKeyguardDone(); // The call to exit should be rejected, and keyguard should still be visible verify(mKeyguardUnlockAnimationController, never()).notifyStartSurfaceBehindRemoteAnimation( any(), any(), any(), anyLong(), anyBoolean()); Loading @@ -389,6 +396,62 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { assertTrue(mViewMediator.isShowingAndNotOccluded()); } @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) public void testGoingAwayFollowedByBeforeUserSwitchWithDelayedExitAnimationDoesNotHideKeyguard() { mUsePostAfterTraversalRunnable = true; int insecureUserId = 1099; setCurrentUser(/* userId= */insecureUserId, /* isSecure= */false); // Setup keyguard mViewMediator.onSystemReady(); processAllMessagesAndBgExecutorMessages(); mViewMediator.setShowingLocked(true, ""); // Request keyguard going away when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); mViewMediator.showSurfaceBehindKeyguard(); // WM will have started the exit animation... RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{ mock(RemoteAnimationTarget.class) }; RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{ mock(RemoteAnimationTarget.class) }; IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class); mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers, null, callback); processAllMessagesAndBgExecutorMessages(); // Followed by a request to dismiss the keyguard completely mViewMediator.mViewMediatorCallback.keyguardDonePending(insecureUserId); mViewMediator.mViewMediatorCallback.readyForKeyguardDone(); // ...but while the exit animation is running, a user switch comes in int nextUserId = 500; setCurrentUser(nextUserId, /* isSecure= */true); Runnable result = mock(Runnable.class); mViewMediator.handleBeforeUserSwitching(nextUserId, result); verify(result).run(); processAllMessagesAndBgExecutorMessages(); // This simulates the race condition in DejankUtils.postAfterTraversal() mPostAfterTraversalRunnable.run(); // At this point, the exit animation should have been canceled, with a true value // indicating that keyguard will be showing verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(eq(true)); try { assertATMSLockScreenShowing(true); } catch (Exception e) { fail(e.getMessage()); } assertTrue(mViewMediator.isShowingAndNotOccluded()); } @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) public void testUserSwitchToSecureUserShowsBouncer() { Loading Loading @@ -1560,7 +1623,17 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mKeyguardTransitionBootInteractor, mKosmos::getCommunalSceneInteractor, mKosmos::getCommunalSettingsInteractor, mock(WindowManagerOcclusionManager.class)); mock(WindowManagerOcclusionManager.class)) { @Override void postAfterTraversal(Runnable runnable) { if (mUsePostAfterTraversalRunnable) { mPostAfterTraversalRunnable = runnable; } else { super.postAfterTraversal(runnable); } } }; mViewMediator.mUserChangedCallback = mUserTrackerCallback; mViewMediator.start(); Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +18 −7 Original line number Diff line number Diff line Loading @@ -682,8 +682,11 @@ public class KeyguardViewMediator implements CoreStartable, Log.d(TAG, String.format("onBeforeUserSwitching %d", userId)); synchronized (KeyguardViewMediator.this) { mHandler.removeCallbacksAndMessages(mDismissToken); mHandler.removeMessages(START_KEYGUARD_EXIT_ANIM); mHandler.removeMessages(DISMISS); mHandler.removeMessages(HIDE); mIsKeyguardExitAnimationCanceled = true; notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); adjustStatusBarLocked(); Loading Loading @@ -3681,6 +3684,12 @@ public class KeyguardViewMediator implements CoreStartable, } } // Allows the runnable to be controlled for tests by overriding this method @VisibleForTesting void postAfterTraversal(Runnable runnable) { DejankUtils.postAfterTraversal(runnable); } /** * Called when we're done running the keyguard exit animation, we should now end up unlocked. * Loading @@ -3700,12 +3709,6 @@ public class KeyguardViewMediator implements CoreStartable, return; } if (mIsKeyguardExitAnimationCanceled) { Log.d(TAG, "Ignoring exitKeyguardAndFinishSurfaceBehindRemoteAnimation. " + "mIsKeyguardExitAnimationCanceled==true"); return; } // Block the panel from expanding, in case we were doing a swipe to dismiss gesture. mKeyguardViewControllerLazy.get().blockPanelExpansionFromCurrentTouch(); final boolean wasShowing = ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS Loading @@ -3713,7 +3716,7 @@ public class KeyguardViewMediator implements CoreStartable, InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION); // Post layout changes to the next frame, so we don't hang at the end of the animation. DejankUtils.postAfterTraversal(() -> { postAfterTraversal(() -> { if (!mPM.isInteractive() && !mPendingLock) { Log.e(TAG, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation#postAfterTraversal:" + " mPM.isInteractive()=" + mPM.isInteractive() Loading @@ -3728,6 +3731,14 @@ public class KeyguardViewMediator implements CoreStartable, return; } if (mIsKeyguardExitAnimationCanceled) { Log.d(TAG, "Ignoring exitKeyguardAndFinishSurfaceBehindRemoteAnimation. " + "mIsKeyguardExitAnimationCanceled==true"); finishSurfaceBehindRemoteAnimation(true /* showKeyguard */); setShowingLocked(true /* showing */, true /* force */, "exitKeyguardAndFinishSurfaceBehindRemoteAnimation - canceled"); return; } onKeyguardExitFinished("exitKeyguardAndFinishSurfaceBehindRemoteAnimation"); Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +75 −2 Original line number Diff line number Diff line Loading @@ -234,12 +234,16 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private FakeFeatureFlags mFeatureFlags; private final int mDefaultUserId = 100; private boolean mUsePostAfterTraversalRunnable; private Runnable mPostAfterTraversalRunnable; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mFalsingCollector = new FalsingCollectorFake(); mSystemClock = new FakeSystemClock(); mUsePostAfterTraversalRunnable = false; mPostAfterTraversalRunnable = null; when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager); when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class)); when(mPowerManager.isInteractive()).thenReturn(true); Loading Loading @@ -307,7 +311,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { */ @After public void assertATMSAndKeyguardViewMediatorStatesMatch() { android.util.Log.i("CLJ", "7"); try { if (mKeyguardGoingAway) { assertATMSKeyguardGoingAway(); Loading Loading @@ -378,6 +381,10 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { null, callback); processAllMessagesAndBgExecutorMessages(); // Followed by a request to dismiss the keyguard completely, which needs to be rejected mViewMediator.mViewMediatorCallback.keyguardDonePending(mDefaultUserId); mViewMediator.mViewMediatorCallback.readyForKeyguardDone(); // The call to exit should be rejected, and keyguard should still be visible verify(mKeyguardUnlockAnimationController, never()).notifyStartSurfaceBehindRemoteAnimation( any(), any(), any(), anyLong(), anyBoolean()); Loading @@ -389,6 +396,62 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { assertTrue(mViewMediator.isShowingAndNotOccluded()); } @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) public void testGoingAwayFollowedByBeforeUserSwitchWithDelayedExitAnimationDoesNotHideKeyguard() { mUsePostAfterTraversalRunnable = true; int insecureUserId = 1099; setCurrentUser(/* userId= */insecureUserId, /* isSecure= */false); // Setup keyguard mViewMediator.onSystemReady(); processAllMessagesAndBgExecutorMessages(); mViewMediator.setShowingLocked(true, ""); // Request keyguard going away when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); mViewMediator.showSurfaceBehindKeyguard(); // WM will have started the exit animation... RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{ mock(RemoteAnimationTarget.class) }; RemoteAnimationTarget[] wallpapers = new RemoteAnimationTarget[]{ mock(RemoteAnimationTarget.class) }; IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class); mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers, null, callback); processAllMessagesAndBgExecutorMessages(); // Followed by a request to dismiss the keyguard completely mViewMediator.mViewMediatorCallback.keyguardDonePending(insecureUserId); mViewMediator.mViewMediatorCallback.readyForKeyguardDone(); // ...but while the exit animation is running, a user switch comes in int nextUserId = 500; setCurrentUser(nextUserId, /* isSecure= */true); Runnable result = mock(Runnable.class); mViewMediator.handleBeforeUserSwitching(nextUserId, result); verify(result).run(); processAllMessagesAndBgExecutorMessages(); // This simulates the race condition in DejankUtils.postAfterTraversal() mPostAfterTraversalRunnable.run(); // At this point, the exit animation should have been canceled, with a true value // indicating that keyguard will be showing verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(eq(true)); try { assertATMSLockScreenShowing(true); } catch (Exception e) { fail(e.getMessage()); } assertTrue(mViewMediator.isShowingAndNotOccluded()); } @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) public void testUserSwitchToSecureUserShowsBouncer() { Loading Loading @@ -1560,7 +1623,17 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mKeyguardTransitionBootInteractor, mKosmos::getCommunalSceneInteractor, mKosmos::getCommunalSettingsInteractor, mock(WindowManagerOcclusionManager.class)); mock(WindowManagerOcclusionManager.class)) { @Override void postAfterTraversal(Runnable runnable) { if (mUsePostAfterTraversalRunnable) { mPostAfterTraversalRunnable = runnable; } else { super.postAfterTraversal(runnable); } } }; mViewMediator.mUserChangedCallback = mUserTrackerCallback; mViewMediator.start(); Loading