Merge "Don't always showSurfaceBehindKeyguard if keyguard exit is cancelled." into tm-qpr-dev

This commit is contained in:
Josh Tsuji
2023-01-05 21:52:34 +00:00
committed by Android (Google) Code Review
4 changed files with 117 additions and 29 deletions

View File

@@ -344,7 +344,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
override fun onAnimationEnd(animation: Animator) { override fun onAnimationEnd(animation: Animator) {
Log.d(TAG, "surfaceBehindEntryAnimator#onAnimationEnd") Log.d(TAG, "surfaceBehindEntryAnimator#onAnimationEnd")
playingCannedUnlockAnimation = false playingCannedUnlockAnimation = false
keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */ false /* cancelled */
) )
} }
@@ -579,7 +579,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
biometricUnlockControllerLazy.get().isWakeAndUnlock -> { biometricUnlockControllerLazy.get().isWakeAndUnlock -> {
Log.d(TAG, "playCannedUnlockAnimation, isWakeAndUnlock") Log.d(TAG, "playCannedUnlockAnimation, isWakeAndUnlock")
setSurfaceBehindAppearAmount(1f) setSurfaceBehindAppearAmount(1f)
keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */) false /* cancelled */)
} }
@@ -627,7 +627,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
return@postDelayed return@postDelayed
} }
keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished( keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */) false /* cancelled */)
}, CANNED_UNLOCK_START_DELAY) }, CANNED_UNLOCK_START_DELAY)
} }
@@ -745,7 +745,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
!keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture && !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture &&
dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) { dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) {
setSurfaceBehindAppearAmount(1f) setSurfaceBehindAppearAmount(1f)
keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false /* cancelled */) keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
} }
} }

View File

@@ -144,12 +144,12 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.DeviceConfigProxy;
import dagger.Lazy;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import dagger.Lazy;
/** /**
* Mediates requests related to the keyguard. This includes queries about the * Mediates requests related to the keyguard. This includes queries about the
* state of the keyguard, power management events that effect whether the keyguard * state of the keyguard, power management events that effect whether the keyguard
@@ -2725,27 +2725,42 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
} }
/** /**
* Called if the keyguard exit animation has been cancelled, and we should dismiss to the * Called if the keyguard exit animation has been cancelled.
* keyguard.
* *
* This can happen due to the system cancelling the RemoteAnimation (due to a timeout, a new * This can happen due to the system cancelling the RemoteAnimation (due to a timeout, a new
* app transition before finishing the current RemoteAnimation). * app transition before finishing the current RemoteAnimation, or the keyguard being re-shown).
*/ */
private void handleCancelKeyguardExitAnimation() { private void handleCancelKeyguardExitAnimation() {
if (mPendingLock) {
Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. "
+ "There's a pending lock, so we were cancelled because the device was locked "
+ "again during the unlock sequence. We should end up locked.");
// A lock is pending, meaning the keyguard exit animation was cancelled because we're
// re-locking. We should just end the surface-behind animation without exiting the
// keyguard. The pending lock will be handled by onFinishedGoingToSleep().
finishSurfaceBehindRemoteAnimation(true);
} else {
Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. "
+ "No pending lock, we should end up unlocked with the app/launcher visible.");
// No lock is pending, so the animation was cancelled during the unlock sequence, but
// we should end up unlocked. Show the surface and exit the keyguard.
showSurfaceBehindKeyguard(); showSurfaceBehindKeyguard();
onKeyguardExitRemoteAnimationFinished(true /* cancelled */); exitKeyguardAndFinishSurfaceBehindRemoteAnimation(true /* cancelled */);
}
} }
/** /**
* Called when we're done running the keyguard exit animation. * Called when we're done running the keyguard exit animation, we should now end up unlocked.
* *
* This will call {@link #mSurfaceBehindRemoteAnimationFinishedCallback} to let WM know that * This will call {@link #handleCancelKeyguardExitAnimation()} to let WM know that we're done
* we're done with the RemoteAnimation, actually hide the keyguard, and clean up state related * with the RemoteAnimation, actually hide the keyguard, and clean up state related to the
* to the keyguard exit animation. * keyguard exit animation.
* *
* @param cancelled {@code true} if the animation was cancelled before it finishes. * @param cancelled {@code true} if the animation was cancelled before it finishes.
*/ */
public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) { public void exitKeyguardAndFinishSurfaceBehindRemoteAnimation(boolean cancelled) {
Log.d(TAG, "onKeyguardExitRemoteAnimationFinished"); Log.d(TAG, "onKeyguardExitRemoteAnimationFinished");
if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) { if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) {
Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled
@@ -2774,10 +2789,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
} }
finishSurfaceBehindRemoteAnimation(cancelled); finishSurfaceBehindRemoteAnimation(cancelled);
mSurfaceBehindRemoteAnimationRequested = false;
// The remote animation is over, so we're not going away anymore.
mKeyguardStateController.notifyKeyguardGoingAway(false);
// Dispatch the callback on animation finishes. // Dispatch the callback on animation finishes.
mUpdateMonitor.dispatchKeyguardDismissAnimationFinished(); mUpdateMonitor.dispatchKeyguardDismissAnimationFinished();
@@ -2836,13 +2847,17 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
return mSurfaceBehindRemoteAnimationRunning; return mSurfaceBehindRemoteAnimationRunning;
} }
/** If it's running, finishes the RemoteAnimation on the surface behind the keyguard. */ /**
* If it's running, finishes the RemoteAnimation on the surface behind the keyguard and resets
* related state.
*
* This does not set keyguard state to either locked or unlocked, it simply ends the remote
* animation on the surface behind the keyguard. This can be called by
*/
void finishSurfaceBehindRemoteAnimation(boolean cancelled) { void finishSurfaceBehindRemoteAnimation(boolean cancelled) {
if (!mSurfaceBehindRemoteAnimationRunning) { mSurfaceBehindRemoteAnimationRequested = false;
return;
}
mSurfaceBehindRemoteAnimationRunning = false; mSurfaceBehindRemoteAnimationRunning = false;
mKeyguardStateController.notifyKeyguardGoingAway(false);
if (mSurfaceBehindRemoteAnimationFinishedCallback != null) { if (mSurfaceBehindRemoteAnimationFinishedCallback != null) {
try { try {

View File

@@ -124,7 +124,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
// Also expect we've immediately asked the keyguard view mediator to finish the remote // Also expect we've immediately asked the keyguard view mediator to finish the remote
// animation. // animation.
verify(keyguardViewMediator, times(1)).onKeyguardExitRemoteAnimationFinished( verify(keyguardViewMediator, times(1)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */) false /* cancelled */)
verifyNoMoreInteractions(surfaceTransactionApplier) verifyNoMoreInteractions(surfaceTransactionApplier)
@@ -144,7 +144,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
) )
// Since the animation is running, we should not have finished the remote animation. // Since the animation is running, we should not have finished the remote animation.
verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished( verify(keyguardViewMediator, times(0)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */) false /* cancelled */)
} }
@@ -272,7 +272,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
assertTrue(remainingTargets.isEmpty()) assertTrue(remainingTargets.isEmpty())
// Since the animation is running, we should not have finished the remote animation. // Since the animation is running, we should not have finished the remote animation.
verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished( verify(keyguardViewMediator, times(0)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */) false /* cancelled */)
} }
} }

View File

@@ -57,6 +57,7 @@ import com.android.keyguard.KeyguardDisplayManager;
import com.android.keyguard.KeyguardSecurityView; import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.mediator.ScreenOnCoordinator; import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.AuthController; import com.android.systemui.biometrics.AuthController;
@@ -160,6 +161,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager, mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager,
mShadeWindowLogger); mShadeWindowLogger);
DejankUtils.setImmediate(true);
createAndStartViewMediator(); createAndStartViewMediator();
} }
@@ -355,9 +358,69 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
verify(mCentralSurfaces).updateIsKeyguard(); verify(mCentralSurfaces).updateIsKeyguard();
} }
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public void testCancelKeyguardExitAnimation_noPendingLock_keyguardWillNotBeShowing() {
startMockKeyguardExitAnimation();
cancelMockKeyguardExitAnimation();
// There should not be a pending lock, but try to handle it anyway to ensure one isn't set.
mViewMediator.maybeHandlePendingLock();
TestableLooper.get(this).processAllMessages();
assertFalse(mViewMediator.isShowingAndNotOccluded());
}
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public void testCancelKeyguardExitAnimationDueToSleep_withPendingLock_keyguardWillBeShowing() {
startMockKeyguardExitAnimation();
mViewMediator.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
mViewMediator.onFinishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, false);
cancelMockKeyguardExitAnimation();
mViewMediator.maybeHandlePendingLock();
TestableLooper.get(this).processAllMessages();
assertTrue(mViewMediator.isShowingAndNotOccluded());
}
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public void testCancelKeyguardExitAnimationThenSleep_withPendingLock_keyguardWillBeShowing() {
startMockKeyguardExitAnimation();
cancelMockKeyguardExitAnimation();
mViewMediator.maybeHandlePendingLock();
TestableLooper.get(this).processAllMessages();
mViewMediator.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
mViewMediator.onFinishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, false);
mViewMediator.maybeHandlePendingLock();
TestableLooper.get(this).processAllMessages();
assertTrue(mViewMediator.isShowingAndNotOccluded());
}
@Test @Test
@TestableLooper.RunWithLooper(setAsMainLooper = true) @TestableLooper.RunWithLooper(setAsMainLooper = true)
public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() { public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() {
startMockKeyguardExitAnimation();
assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
}
/**
* Configures mocks appropriately, then starts the keyguard exit animation.
*/
private void startMockKeyguardExitAnimation() {
mViewMediator.onSystemReady();
TestableLooper.get(this).processAllMessages();
mViewMediator.setShowingLocked(true);
RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{ RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
mock(RemoteAnimationTarget.class) mock(RemoteAnimationTarget.class)
}; };
@@ -366,10 +429,19 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
}; };
IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class); IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers, mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
null, callback); null, callback);
TestableLooper.get(this).processAllMessages(); TestableLooper.get(this).processAllMessages();
assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()); }
/**
* Configures mocks appropriately, then cancels the keyguard exit animation.
*/
private void cancelMockKeyguardExitAnimation() {
when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
mViewMediator.cancelKeyguardExitAnimation();
TestableLooper.get(this).processAllMessages();
} }
private void createAndStartViewMediator() { private void createAndStartViewMediator() {