@startuml
[-> BiometricUnlockController: onBiometricAuthenticated
BiometricUnlockController->BiometricUnlockController: startWakeAndUnlock()
BiometricUnlockController->StatusBarKeyguardViewManager:notifyKeyguardAuthenticated()
StatusBarKeyguardViewManager->KeyguardBouncer:notifyKeyguardAuthenticated
KeyguardBouncer->KeyguardHostViewController:finish
KeyguardHostViewController->SecurityCallback:finish
SecurityCallback->ViewMediatorCallback:keyguardDone(strongAuth, targetUserId)
ViewMediatorCallback->KeyguardViewMediator: tryKeyguardDone()
KeyguardViewMediator->StatusBarKeyguardViewManager:startPreHideAnimation(mHideAnimationFinishedRunnable)
StatusBarKeyguardViewManager->KeyguardViewMediator:mHideAnimationFinishedRunnable.run()
KeyguardViewMediator->KeyguardViewMediator:tryKeyguardDone()
KeyguardViewMediator->KeyguardViewMediator:handleKeyguardDone()
KeyguardViewMediator->KeyguardViewMediator:handleHide()
KeyguardViewMediator->KeyguardViewMediator: mKeyguardGoingAwayRunnable.run()
note over KeyguardViewMediator : PhoneWindowManager 将会在 AppTransition 执行结束后通知 KeyguardService
KeyguardViewMediator->KeyguardViewMediator:handleStartKeyguardExitAnimation()
KeyguardViewMediator->StatusBarKeyguardViewManager:hide()
@enduml
com.android.keyguard.KeyguardUpdateMonitor#onFingerprintAuthenticated
@VisibleForTesting
protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
Assert.isMainThread();
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId,
new BiometricAuthenticated(true, isStrongBiometric));
// Update/refresh trust state only if user can skip bouncer
if (getUserCanSkipBouncer(userId)) {
mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FINGERPRINT);
}
// Don't send cancel if authentication succeeds
mFingerprintCancelSignal = null;
updateBiometricListeningState();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthenticated(userId, BiometricSourceType.FINGERPRINT,
isStrongBiometric);//1
}
}
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE),
FINGERPRINT_CONTINUE_DELAY_MS);
// Only authenticate fingerprint once when assistant is visible
mAssistantVisible = false;
// Report unlock with strong or non-strong biometric
reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
Trace.endSection();
}
指纹解锁成功后,会在注释 1 处调用注册到 KeyguardUpdateMonitor 的 Callback ,其中包括:
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.policy.KeyguardStateControllerImpl$UpdateMonitorCallback@5e3a4c1
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.keyguard.KeyguardSliceProvider$2@555416f
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.classifier.FalsingCollectorImpl$2@6d617e5
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.sonymobile.keyguard.statistics.LockscreenStatisticsFingerprintAccuracyReporter@71a354b
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.doze.DozeLog$1@3d0dc47
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.BiometricUnlockController@8f59c74
04-29 22:31:10.583 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController$1@a0a0be0
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.KeyguardIndicationController$BaseKeyguardCallback@fd4f972
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.KeyguardIndicationController$4@e68fa40
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.sonymobile.keyguard.aod.FingerPrintFeedBackView$FingerprintFBCallBack@7dda55a
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.ScrimController$KeyguardVisibilityCallback@9f98ed2
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.notification.collection.coordinator.KeyguardCoordinator$6@380d706
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.KeyguardBouncer$1@2584c90
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager$3@e4ca989
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.StatusBar$5@b421d8e
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.wmshell.WMShell$2@95f5b5a
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.wmshell.WMShell$4@977d681
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.wmshell.WMShell$7@427d326
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.NotificationPanelViewController$1@a68d435
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.statusbar.phone.KeyguardBottomAreaView$10@1c33f70
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.EmergencyButtonController$1@e1652e9
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.LockIconViewController$3@5fa7b6e
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.KeyguardStatusViewController$2@256420f
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.AnimatableClockController$4@f40e934
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.AnimatableClockController$4@7e9535d
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.biometrics.AuthRippleController$keyguardUpdateMonitorCallback$1@b0147f
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.systemui.keyguard.KeyguardViewMediator$2@3b8279e
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.KeyguardHostViewController$1@3a7df7b
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.KeyguardPINView$1@8c81870
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.KeyguardMessageAreaController$1@b44b7e9
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.EmergencyButtonController$1@3817c6e
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.CarrierTextManager$2@9a65f9a
04-29 22:31:10.584 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.CarrierTextManager$2@3d5a25a
04-29 22:31:10.585 29196 29196 D KeyguardUpdateMonitor: onFingerprintAuthenticated: com.android.keyguard.CarrierTextManager$2@4ec50f9
其中 AuthRippleController 负责绘制波澜效果
指纹解锁成功的消息通过回调传递给 BiometricUnlockController
推动 Keyguard 继续走消去流程的是 BiometricUnlockController 的 callback
com.android.systemui.statusbar.phone.BiometricUnlockController#onBiometricAuthenticated
@Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
if (mUpdateMonitor.isGoingToSleep()) {
mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
isStrongBiometric);
Trace.endSection();
return;
}
mBiometricType = biometricSourceType;
mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
.setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
.ifPresent(UI_EVENT_LOGGER::log);
boolean unlockAllowed =
mKeyguardStateController.isOccluded()
|| mKeyguardBypassController.onBiometricAuthenticated(
biometricSourceType, isStrongBiometric);
if (unlockAllowed) {
mKeyguardViewMediator.userActivity();
startWakeAndUnlock(biometricSourceType, isStrongBiometric);//1
} else {
Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
}
}
在注释 1 处调用 com.android.systemui.statusbar.phone.BiometricUnlockController#startWakeAndUnlock(BiometricSourceType, boolean)
public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
startWakeAndUnlock(calculateMode(biometricSourceType, isStrongBiometric));//1
}
private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
if (biometricSourceType == BiometricSourceType.FACE
|| biometricSourceType == BiometricSourceType.IRIS) {
return calculateModeForPassiveAuth(isStrongBiometric);
} else {
return calculateModeForFingerprint(isStrongBiometric);//2
}
}
private @WakeAndUnlockMode int calculateModeForFingerprint(boolean isStrongBiometric) {
boolean unlockingAllowed =
mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
boolean deviceDreaming = mUpdateMonitor.isDreaming();
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mKeyguardViewController.isShowing()) {
return MODE_ONLY_WAKE;
} else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
return MODE_WAKE_AND_UNLOCK_PULSING;
} else if (unlockingAllowed || !mKeyguardStateController.isMethodSecure()) {
return MODE_WAKE_AND_UNLOCK;
} else {
return MODE_SHOW_BOUNCER;
}
}
if (unlockingAllowed && deviceDreaming) {
return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
}
if (mKeyguardViewController.isShowing()) {
if (mKeyguardViewController.bouncerIsOrWillBeShowing() && unlockingAllowed) {
return MODE_DISMISS_BOUNCER;
} else if (unlockingAllowed) {
return MODE_UNLOCK_COLLAPSING;//3
} else if (!mKeyguardViewController.isBouncerShowing()) {
return MODE_SHOW_BOUNCER;
}
}
return MODE_NONE;
}
屏幕点亮的时候,进行指纹解锁,log输出为 BiometricUnlockCtrl: startWakeAndUnlock(5),即 MODE_UNLOCK_COLLAPSING,该整型将作为参数传递给 com.android.systemui.statusbar.phone.BiometricUnlockController#startWakeAndUnlock(int)
public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = mode;
mHasScreenTurnedOnSinceAuthenticating = false;
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
// If we are waking the device up while we are pulsing the clock and the
// notifications would light up first, creating an unpleasant animation.
// Defer changing the screen brightness by forcing doze brightness on our window
// until the clock and the notifications are faded out.
mNotificationShadeWindowController.setForceDozeBrightness(true);
}
// During wake and unlock, we need to draw black before waking up to avoid abrupt
// brightness changes due to display state transitions.
boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
Runnable wakeUp = ()-> {
if (!wasDeviceInteractive) {
if (DEBUG_BIO_WAKELOCK) {
Log.i(TAG, "bio wakelock: Authenticated, waking up...");
}
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"android.policy:BIOMETRIC");
}
if (delayWakeUp) {
mKeyguardViewMediator.onWakeAndUnlocking();
}
Trace.beginSection("release wake-and-unlock");
releaseBiometricWakeLock();
Trace.endSection();
};
if (!delayWakeUp && mMode != MODE_NONE) {
wakeUp.run();
}
switch (mMode) {
case MODE_DISMISS_BOUNCER:
case MODE_UNLOCK_FADING:
Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING");
mKeyguardViewController.notifyKeyguardAuthenticated(
false /* strongAuth */);
Trace.endSection();
break;
case MODE_UNLOCK_COLLAPSING:
Trace.beginSection("MODE_UNLOCK_COLLAPSING");
if (!wasDeviceInteractive) {
mPendingShowBouncer = true;
} else {
mPendingShowBouncer = false;
mKeyguardViewController.notifyKeyguardAuthenticated(
false /* strongAuth */);//1
}
Trace.endSection();
break;
case MODE_SHOW_BOUNCER:
Trace.beginSection("MODE_SHOW_BOUNCER");
if (!wasDeviceInteractive) {
mPendingShowBouncer = true;
} else {
showBouncer();
}
Trace.endSection();
break;
case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
case MODE_WAKE_AND_UNLOCK_PULSING:
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
} else if (mMode == MODE_WAKE_AND_UNLOCK){
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
} else {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
mUpdateMonitor.awakenFromDream();
}
mNotificationShadeWindowController.setNotificationShadeFocusable(false);
if (delayWakeUp) {
mHandler.postDelayed(wakeUp, mWakeUpDelay);
} else {
mKeyguardViewMediator.onWakeAndUnlocking();
}
Trace.endSection();
break;
case MODE_ONLY_WAKE:
case MODE_NONE:
break;
}
onModeChanged(mMode);
if (mBiometricModeListener != null) {
mBiometricModeListener.notifyBiometricAuthModeChanged();
}
Trace.endSection();
}
注释 1 处的 mKeyguardViewController 为 StatusBarKeyguardViewManager,所以该处调用了 com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager#notifyKeyguardAuthenticated
public void notifyKeyguardAuthenticated(boolean strongAuth) {
mBouncer.notifyKeyguardAuthenticated(strongAuth);//1
if (mAlternateAuthInterceptor != null && isShowingAlternateAuthOrAnimating()) {
resetAlternateAuth(false);
executeAfterKeyguardGoneAction();
}
}
注释 1 处调了 com.android.systemui.statusbar.phone.KeyguardBouncer#notifyKeyguardAuthenticated
public void notifyKeyguardAuthenticated(boolean strongAuth) {
ensureView();//1
mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());//2
}
protected void ensureView() {
// Removal of the view might be deferred to reduce unlock latency,
// in this case we need to force the removal, otherwise we'll
// end up in an unpredictable state.
boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
if (mRoot == null || forceRemoval) {
inflateView();
}
}
因为 mRoot 存在,所以注释 1 的代码并没有什么意义,继续注释 2 的逻辑,mKeyguardViewController 即 KeyguardHostViewController,该处调用为
com.android.keyguard.KeyguardHostViewController#finish
public void finish(boolean strongAuth, int currentUser) {
mSecurityCallback.finish(strongAuth, currentUser);
}
//com.android.keyguard.KeyguardHostViewController#mSecurityCallback
private final SecurityCallback mSecurityCallback = new SecurityCallback() {
@Override
public boolean dismiss(boolean authenticated, int targetUserId,
boolean bypassSecondaryLockScreen) {
return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
authenticated, targetUserId, bypassSecondaryLockScreen);
}
@Override
public void userActivity() {
mViewMediatorCallback.userActivity();
}
@Override
public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
mViewMediatorCallback.setNeedsInput(needsInput);
}
/**
* Authentication has happened and it's time to dismiss keyguard. This function
* should clean up and inform KeyguardViewMediator.
*
* @param strongAuth whether the user has authenticated with strong authentication like
* pattern, password or PIN but not by trust agents or fingerprint
* @param targetUserId a user that needs to be the foreground user at the dismissal
* completion.
*/
@Override
public void finish(boolean strongAuth, int targetUserId) {
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
boolean deferKeyguardDone = false;
if (mDismissAction != null) {
deferKeyguardDone = mDismissAction.onDismiss();
mDismissAction = null;
mCancelAction = null;
}
if (mViewMediatorCallback != null) {
if (deferKeyguardDone) {
mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
} else {
mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);//1
}
}
}
@Override
public void reset() {
mViewMediatorCallback.resetKeyguard();
}
@Override
public void onCancelClicked() {
mViewMediatorCallback.onCancelClicked();
}
};
走到注释 1 处,开始进入解锁流程 mViewMediatorCallback 来自 com.android.systemui.keyguard.KeyguardViewMediator#mViewMediatorCallback
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
@Override
public void userActivity() {
KeyguardViewMediator.this.userActivity();
}
@Override
public void keyguardDone(boolean strongAuth, int targetUserId) {
if (targetUserId != ActivityManager.getCurrentUser()) {
return;
}
if (DEBUG) Log.d(TAG, "keyguardDone");
tryKeyguardDone();//1
}
@Override
public void keyguardDoneDrawing() {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardDoneDrawing");
mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
Trace.endSection();
}
@Override
public void setNeedsInput(boolean needsInput) {
mKeyguardViewControllerLazy.get().setNeedsInput(needsInput);
}
@Override
public void keyguardDonePending(boolean strongAuth, int targetUserId) {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardDonePending");
if (DEBUG) Log.d(TAG, "keyguardDonePending");
if (targetUserId != ActivityManager.getCurrentUser()) {
Trace.endSection();
return;
}
mKeyguardDonePending = true;
mHideAnimationRun = true;
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get()
.startPreHideAnimation(mHideAnimationFinishedRunnable);
mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_PENDING_TIMEOUT,
KEYGUARD_DONE_PENDING_TIMEOUT_MS);
Trace.endSection();
}
@Override
public void keyguardGone() {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardGone");
if (DEBUG) Log.d(TAG, "keyguardGone");
mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
mKeyguardDisplayManager.hide();
Trace.endSection();
}
@Override
public void readyForKeyguardDone() {
Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#readyForKeyguardDone");
if (mKeyguardDonePending) {
mKeyguardDonePending = false;
tryKeyguardDone();
}
Trace.endSection();
}
@Override
public void resetKeyguard() {
resetStateLocked();
}
@Override
public void onCancelClicked() {
mKeyguardViewControllerLazy.get().onCancelClicked();
}
@Override
public void onBouncerVisiblityChanged(boolean shown) {
synchronized (KeyguardViewMediator.this) {
adjustStatusBarLocked(shown, false);
}
}
@Override
public void playTrustedSound() {
KeyguardViewMediator.this.playTrustedSound();
}
@Override
public boolean isScreenOn() {
return mDeviceInteractive;
}
@Override
public int getBouncerPromptReason() {
int currentUser = KeyguardUpdateMonitor.getCurrentUser();
boolean trust = mUpdateMonitor.isTrustUsuallyManaged(currentUser);
boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser);
boolean any = trust || biometrics;
KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
mUpdateMonitor.getStrongAuthTracker();
int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
return KeyguardSecurityView.PROMPT_REASON_RESTART;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
} else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
} else if (any && (strongAuth
& STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
}
return KeyguardSecurityView.PROMPT_REASON_NONE;
}
@Override
public CharSequence consumeCustomMessage() {
final CharSequence message = mCustomMessage;
mCustomMessage = null;
return message;
}
};
这里走了注释 1 的逻辑,即下一步调用了
com.android.systemui.keyguard.KeyguardViewMediator#tryKeyguardDone
private void tryKeyguardDone() {
if (DEBUG) {
Log.d(TAG, "tryKeyguardDone: pending - " + mKeyguardDonePending + ", animRan - "
+ mHideAnimationRun + " animRunning - " + mHideAnimationRunning);
}
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();
} else if (!mHideAnimationRun) {
if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
mHideAnimationRun = true; //1
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get()
.startPreHideAnimation(mHideAnimationFinishedRunnable);//1
}
}
首次调用该函数时因为 mHideAnimationRun 仍然为 false,所以走了下面的分支,首先在注释 1 处,将 mHideAnimationRun 置为 true,然后在注释 2 处开始执行播放解锁前的 hide 动画,动画播放结束后,将调用 mHideAnimationFinishedRunnable 回调
com.android.systemui.keyguard.KeyguardViewMediator#mHideAnimationFinishedRunnable
private final Runnable mHideAnimationFinishedRunnable = () -> {
Log.e(TAG, "mHideAnimationFinishedRunnable#run");
mHideAnimationRunning = false;
tryKeyguardDone();//1
};
private void tryKeyguardDone() {
if (DEBUG) {
Log.d(TAG, "tryKeyguardDone: pending - " + mKeyguardDonePending + ", animRan - "
+ mHideAnimationRun + " animRunning - " + mHideAnimationRunning);
}
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();//2
} else if (!mHideAnimationRun) {
if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
mHideAnimationRun = true;
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get()
.startPreHideAnimation(mHideAnimationFinishedRunnable);
}
}
在 mHideAnimationFinishedRunnable 中将第二次调用 tryKeyguardDone(),这一次因为 mHideAnimationRun 在上一次调用时被置为了 true,所以走了上面的分支,即执行了注释 2 的逻辑
com.android.systemui.keyguard.KeyguardViewMediator#handleKeyguardDone
private void handleKeyguardDone() {
Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
mUiBgExecutor.execute(() -> {
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
}
});
if (DEBUG) Log.d(TAG, "handleKeyguardDone");
synchronized (this) {
resetKeyguardDonePendingLocked();
}
if (mGoingToSleep) {
mUpdateMonitor.clearBiometricRecognized();
Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
return;
}
if (mExitSecureCallback != null) {
try {
mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult()", e);
}
mExitSecureCallback = null;
// after succesfully exiting securely, no need to reshow
// the keyguard when they've released the lock
mExternallyEnabled = true;
mNeedToReshowWhenReenabled = false;
updateInputRestricted();
}
handleHide();//1
mUpdateMonitor.clearBiometricRecognized();
Trace.endSection();
}
继续在注释 1 处调用
com.android.systemui.keyguard.KeyguardViewMediator#handleHide
private void handleHide() {
Trace.beginSection("KeyguardViewMediator#handleHide");
// It's possible that the device was unlocked in a dream state. It's time to wake up.
if (mAodShowing) {
PowerManager pm = mContext.getSystemService(PowerManager.class);
pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:BOUNCER_DOZING");
}
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleHide");
if (mustNotUnlockCurrentUser()) {
// In split system user mode, we never unlock system user. The end user has to
// switch to another user.
// TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
// still completes and makes the screen blank.
if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
mKeyguardExitAnimationRunner = null;
return;
}
mHiding = true;
if (mShowing && !mOccluded) {//1
mKeyguardGoingAwayRunnable.run();//2
} else {
// TODO(bc-unlock): Fill parameters
handleStartKeyguardExitAnimation(
SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */,
null /* nonApps */, null /* finishedCallback */);
}
}
Trace.endSection();
}
此时由于锁屏界面还未消失,所以注释 1 的判断成立,走了注释 2 的逻辑
com.android.systemui.keyguard.KeyguardViewMediator#mKeyguardGoingAwayRunnable
private final Runnable mKeyguardGoingAwayRunnable = new Runnable() {
@Override
public void run() {
Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
if (DEBUG) Log.d(TAG, "keyguardGoingAway");
mKeyguardViewControllerLazy.get().keyguardGoingAway();
int flags = 0;
if (mKeyguardViewControllerLazy.get().shouldDisableWindowAnimationsForUnlock()
|| (mWakeAndUnlocking && !mPulsing)
|| isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) {
flags |= WindowManagerPolicyConstants
.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
}
if (mKeyguardViewControllerLazy.get().isGoingToNotificationShade()
|| (mWakeAndUnlocking && mPulsing)) {
flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
}
if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
flags |= KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
}
if (mKeyguardViewControllerLazy.get().shouldSubtleWindowAnimationsForUnlock()) {
flags |= WindowManagerPolicyConstants
.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
}
mUpdateMonitor.setKeyguardGoingAway(true);
mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(true);
// Don't actually hide the Keyguard at the moment, wait for window
// manager until it tells us it's safe to do so with
// startKeyguardExitAnimation.
// Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
// order.
final int keyguardFlag = flags;
mUiBgExecutor.execute(() -> {
try {
ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);//1
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
});
Trace.endSection();
}
};
该函数最终在注释 1 处将锁屏即将消失的信息传递给了 ATM,ATM 开始安排锁屏后面的 Activity (比如 Launcher )执行进场动画,当后面的 Activity 动画执行完,将通过回调通知锁屏,锁屏最终会调用
com.android.systemui.keyguard.KeyguardViewMediator#handleStartKeyguardExitAnimation,至此才开始处理锁屏界面消失的逻辑
private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) {
Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
+ " fadeoutDuration=" + fadeoutDuration);
synchronized (KeyguardViewMediator.this) {
// Tell ActivityManager that we canceled the keyguard animation if
// handleStartKeyguardExitAnimation was called but we're not hiding the keyguard, unless
// we're animating the surface behind the keyguard and will be hiding the keyguard
// shortly.
if (!mHiding
&& !mSurfaceBehindRemoteAnimationRequested
&& !mKeyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture()) {
if (finishedCallback != null) {
// There will not execute animation, send a finish callback to ensure the remote
// animation won't hanging there.
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationFinished", e);
}
}
setShowingLocked(mShowing, true /* force */);
return;
}
mHiding = false;
IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner;
mKeyguardExitAnimationRunner = null;
if (mWakeAndUnlocking && mDrawnCallback != null) {
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
// the next draw from here so we don't have to wait for window manager to signal
// this to our ViewRootImpl.
mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
notifyDrawn(mDrawnCallback);
mDrawnCallback = null;
}
LatencyTracker.getInstance(mContext)
.onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation && runner != null
&& finishedCallback != null) {
// Wrap finishedCallback to clean up the keyguard state once the animation is done.
IRemoteAnimationFinishedCallback callback =
new IRemoteAnimationFinishedCallback() {
@Override
public void onAnimationFinished() throws RemoteException {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationFinished", e);
}
onKeyguardExitFinished();
mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
0 /* fadeoutDuration */);
InteractionJankMonitor.getInstance()
.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
@Override
public IBinder asBinder() {
return finishedCallback.asBinder();
}
};
try {
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("RunRemoteAnimation"));
runner.onAnimationStart(WindowManager.TRANSIT_KEYGUARD_GOING_AWAY, apps,
wallpapers, nonApps, callback);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationStart", e);
}
// When remaining on the shade, there's no need to do a fancy remote animation,
// it will dismiss the panel in that case.
} else if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()
&& apps != null && apps.length > 0) {
mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
mSurfaceBehindRemoteAnimationRunning = true;
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("DismissPanel"));
// Pass the surface and metadata to the unlock animation controller.
mKeyguardUnlockAnimationControllerLazy.get().notifyStartKeyguardExitAnimation(
apps[0], startTime, mSurfaceBehindRemoteAnimationRequested);
} else {
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("RemoteAnimationDisabled"));
mKeyguardViewControllerLazy.get().hide(startTime, fadeoutDuration);//1
// TODO(bc-animation): When remote animation is enabled for keyguard exit animation,
// apps, wallpapers and finishedCallback are set to non-null. nonApps is not yet
// supported, so it's always null.
mContext.getMainExecutor().execute(() -> {
if (finishedCallback == null) {
InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
return;
}
// TODO(bc-unlock): Sample animation, just to apply alpha animation on the app.
final SyncRtSurfaceTransactionApplier applier =
new SyncRtSurfaceTransactionApplier(
mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
final RemoteAnimationTarget primary = apps[0];
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
anim.setDuration(400 /* duration */);
anim.setInterpolator(Interpolators.LINEAR);
anim.addUpdateListener((ValueAnimator animation) -> {
SyncRtSurfaceTransactionApplier.SurfaceParams params =
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
primary.leash)
.withAlpha(animation.getAnimatedFraction())
.build();
applier.scheduleApply(params);
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException");
} finally {
InteractionJankMonitor.getInstance()
.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
}
@Override
public void onAnimationCancel(Animator animation) {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException");
} finally {
InteractionJankMonitor.getInstance()
.cancel(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
}
});
anim.start();
});
onKeyguardExitFinished();
}
}
Trace.endSection();
}
注释 1 控制锁屏的界面的渐变与消失
com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager#hide
public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
mKeyguardStateController.notifyKeyguardState(mShowing,
mKeyguardStateController.isOccluded());
launchPendingWakeupAction();
if (mKeyguardUpdateManager.needsSlowUnlockTransition()) {
fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
}
long uptimeMillis = SystemClock.uptimeMillis();
long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
if (mStatusBar.isInLaunchTransition()
|| mKeyguardStateController.isFlingingToDismissKeyguard()) {// 注释 1
final boolean wasFlingingToDismissKeyguard =
mKeyguardStateController.isFlingingToDismissKeyguard();
mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
@Override
public void run() {
mNotificationShadeWindowController.setKeyguardShowing(false);
mNotificationShadeWindowController.setKeyguardFadingAway(true);
hideBouncer(true /* destroyView */);
updateStates();
}
}, new Runnable() {
@Override
public void run() {
mStatusBar.hideKeyguard();
mNotificationShadeWindowController.setKeyguardFadingAway(false);
if (wasFlingingToDismissKeyguard) {
mStatusBar.finishKeyguardFadingAway();
}
mViewMediatorCallback.keyguardGone();
executeAfterKeyguardGoneAction();
}
});
} else {
executeAfterKeyguardGoneAction();
boolean wakeUnlockPulsing =
mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
boolean needsFading = needsBypassFading();
if (needsFading) {
delay = 0;
fadeoutDuration = KeyguardBypassController.BYPASS_FADE_DURATION;
} else if (wakeUnlockPulsing) {
delay = 0;
fadeoutDuration = 240;
}
mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading);
mBiometricUnlockController.startKeyguardFadingAway();
hideBouncer(true /* destroyView */); //注释2
if (wakeUnlockPulsing) {// 注释 3
if (needsFading) {
ViewGroupFadeHelper.fadeOutAllChildrenExcept(
mNotificationPanelViewController.getView(),
mNotificationContainer,
fadeoutDuration,
() -> {
mStatusBar.hideKeyguard();
onKeyguardFadedAway();
});
} else {
mStatusBar.fadeKeyguardWhilePulsing();
}
wakeAndUnlockDejank();
} else {
boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
if (!staying) {
mNotificationShadeWindowController.setKeyguardFadingAway(true);
if (needsFading) {
ViewGroupFadeHelper.fadeOutAllChildrenExcept(
mNotificationPanelViewController.getView(),
mNotificationContainer,
fadeoutDuration,
() -> {
mStatusBar.hideKeyguard();
});
} else {
mStatusBar.hideKeyguard(); // 注释4
}
// hide() will happen asynchronously and might arrive after the scrims
// were already hidden, this means that the transition callback won't
// be triggered anymore and StatusBarWindowController will be forever in
// the fadingAway state.
mStatusBar.updateScrimController();
wakeAndUnlockDejank();
} else {
mStatusBar.hideKeyguard();
mStatusBar.finishKeyguardFadingAway();
mBiometricUnlockController.finishKeyguardFadingAway();
}
}
updateStates(); // 注释5
mNotificationShadeWindowController.setKeyguardShowing(false);
mViewMediatorCallback.keyguardGone();
}
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
}
注释 1 的判断语句不成立,所以走 else 流程,调用注释 2 处的代码移除 bouncer view。随后,由于注释 3 处的条件也不成立,走 else 流程,最终走到注释 4 将通知与桌面时钟隐藏。最后调用注释 5 更新 Keyguard 的状态