前面的文章分析了上锁的流程,解锁的流程可以看作是上锁的逆过程,同样有以下三点
- 设备认证
- 移除锁屏,或者说是statusbar由锁屏模式切换为状态栏模式,改变窗口大小,移除bouncer
- 更新activity stack状态,这个在前面讲apptransition有提到过
1.密码界面解锁
输入密码后,会调用到下面这段函数,通过回调的方式来获取到密码校验的结果,其中LockPatternUtils扮演了类似于xxManager的作用,把检验密码的命令发送到LockSettingsService,最终直达GateKeeper,再一层层传回结果,密码校验的过程也是十分复杂,这里不做分析
mPendingLockCheck = LockPatternChecker.checkPassword(mLockPatternUtils, entry, userId,
new LockPatternChecker.OnCheckCallback() {
@Override
public void onEarlyMatched() {
onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */, true /* isValidPassword */);
}
@Override
public void onChecked(boolean matched, int timeoutMs) {
setPasswordEntryInputEnabled(true);
mPendingLockCheck = null;
if (!matched) {
onPasswordChecked(userId, false /* matched */, timeoutMs, true /* isValidPassword */);
}
}
});
完成密码校验后最终来到KeyguardViewMediator的handleKeyguardDone函数,类似于doKeyguardLocked,都是上锁或解锁的起始函数
private void handleKeyguardDone(boolean authenticated) {
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser); // 通知devicepolicymanagerservice
}
synchronized (this) {
resetKeyguardDonePendingLocked();
}
if (authenticated) {
mUpdateMonitor.clearFailedUnlockAttempts();
}
mUpdateMonitor.clearFingerprintRecognized();
if (mGoingToSleep) {
return;
}
if (mExitSecureCallback != null) {
try {
mExitSecureCallback.onKeyguardExitResult(authenticated);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
}
mExitSecureCallback = null;
if (authenticated) {
mExternallyEnabled = true;
mNeedToReshowWhenReenabled = false;
updateInputRestricted();
}
}
handleHide(); // 处理移除锁屏
}
handleHide首先会执行一个apptransition,这里面就会完成activity stack的更新,前面也说过,执行完apptransition又会调到handleStartKeyguardExitAnimation
private final Runnable mKeyguardGoingAwayRunnable = new Runnable() {
@Override
public void run() {
try {
mStatusBarKeyguardViewManager.keyguardGoingAway();
int flags = 0;
if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
|| mWakeAndUnlocking) {
flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
}
if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) {
flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
}
if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
}
ActivityManagerNative.getDefault().keyguardGoingAway(flags);
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
}
};
private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
synchronized (KeyguardViewMediator.this) {
if (!mHiding) {
return;
}
mHiding = false;
if (mWakeAndUnlocking && mDrawnCallback != null) {
mStatusBarKeyguardViewManager.getViewRootImpl().setReportNextDraw();
notifyDrawn(mDrawnCallback);
mDrawnCallback = null;
}
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
playSounds(false);
}
mWakeAndUnlocking = false;
setShowingLocked(false);
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration); // 收起锁屏并隐藏bouncer
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
updateActivityLockScreenState();
adjustStatusBarLocked();
sendUserPresentBroadcast();
}
}
StatusBarKeyguardViewManager中的hide和show函数也是相互对应的关系,这里也会涉及到很多场景的处理,一般情况下的解锁过程已经标注出来,经过解锁流程,锁屏界面消失,锁屏下的界面显示出来
public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
}
long uptimeMillis = SystemClock.uptimeMillis();
long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
if (mPhoneStatusBar.isInLaunchTransition() ) {
mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
@Override
public void run() {
mStatusBarWindowManager.setKeyguardShowing(false);
mStatusBarWindowManager.setKeyguardFadingAway(true);
mBouncer.hide(true /* destroyView */);
updateStates();
mScrimController.animateKeyguardFadingOut(
PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
PhoneStatusBar.FADE_KEYGUARD_DURATION, null,
false /* skipFirstFrame */);
}
}, new Runnable() {
@Override
public void run() {
mPhoneStatusBar.hideKeyguard();
mStatusBarWindowManager.setKeyguardFadingAway(false);
mViewMediatorCallback.keyguardGone();
executeAfterKeyguardGoneAction();
}
});
} else {
if (mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
mFingerprintUnlockController.startKeyguardFadingAway();
mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 240);
mStatusBarWindowManager.setKeyguardFadingAway(true);
mPhoneStatusBar.fadeKeyguardWhilePulsing();
animateScrimControllerKeyguardFadingOut(0, 240, new Runnable() {
@Override
public void run() {
mPhoneStatusBar.hideKeyguard();
}
}, false /* skipFirstFrame */);
} else {
// 一般情况
mFingerprintUnlockController.startKeyguardFadingAway();
mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
boolean staying = mPhoneStatusBar.hideKeyguard();
if (!staying) {
mStatusBarWindowManager.setKeyguardFadingAway(true);
if (mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) {
if (!mScreenTurnedOn) {
mDeferScrimFadeOut = true;
} else {
animateScrimControllerKeyguardFadingOut(0,WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS, true /* skipFirstFrame */);
}
} else {
animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration, false /* skipFirstFrame */);
}
} else {
mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
mPhoneStatusBar.finishKeyguardFadingAway();
}
}
mStatusBarWindowManager.setKeyguardShowing(false);
mBouncer.hide(true /* destroyView */);
mViewMediatorCallback.keyguardGone();
executeAfterKeyguardGoneAction();
updateStates();
}
}
2.指纹解锁
Android6.0加入了指纹解锁的功能,指纹解锁和密码解锁的主要区别是指纹的认证是由FingerprintService传递过来的,并非LockSettingsService,当然指纹和密码也有很多其他的联系,这里不详述
锁屏处理指纹监听与结果回调的类是KeyguardUpdateMonitor,进一步地,它会把结果传递到FingprintUnlockController
public void onFingerprintAuthenticated(int userId) {
if (mUpdateMonitor.isGoingToSleep()) {
mPendingAuthenticatedUserId = userId;
return;
}
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = calculateMode();
if (!wasDeviceInteractive) {
mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
}
releaseFingerprintWakeLock();
switch (mMode) {
case MODE_DISMISS_BOUNCER:
mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
false /* strongAuth */);
break;
case MODE_UNLOCK:
case MODE_SHOW_BOUNCER:
if (!wasDeviceInteractive) {
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
break;
case MODE_WAKE_AND_UNLOCK_PULSING:
mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
case MODE_WAKE_AND_UNLOCK:
mStatusBarWindowManager.setStatusBarFocusable(false);
mDozeScrimController.abortPulsing();
mKeyguardViewMediator.onWakeAndUnlocking();
mScrimController.setWakeAndUnlocking();
if (mPhoneStatusBar.getNavigationBarView() != null) {
mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
break;
case MODE_ONLY_WAKE:
case MODE_NONE:
break;
}
if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
mStatusBarWindowManager.setForceDozeBrightness(false);
}
mPhoneStatusBar.notifyFpAuthModeChanged();
}
如果当前屏幕熄灭,那么指纹认证成功后还会点亮屏幕,同时也会根据当前的场景去执行相应的解锁流程,但是不管是mStatusBarKeyguardViewManager.animateCollapsePanels(FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR)还是mKeyguardViewMediator.onWakeAndUnlocking(),最终结果都会是KeyguardViewMediator的handleKeyguardDone函数,殊途同归
3.时序图

网友评论