Android6.0 keyguard锁屏加载流程分析

来源:互联网 发布:海安东华软件招聘 编辑:程序博客网 时间:2024/06/17 01:54

锁屏界面的加载通常在android中有两种方式触发:android系统开机和screenOff(灭屏)后,再screenOn;

先来看

android系统开机时候的锁屏加载流程
首先在系统启动过程中,会进入到SystemServer.java的startOtherServices()方法:

初始化WindowManagerService;

[java] view plain copy
  1. wm = WindowManagerService.main(context, inputManager,  
  2.                     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,  
  3.                     !mFirstBoot, mOnlyCore);  
调用systemReady()方法,表示系统准备启动;

[java] view plain copy
  1. try {  
  2.             wm.systemReady();  
  3.         } catch (Throwable e) {  
  4.             reportWtf("making Window Manager Service ready", e);  
  5.         }  
调用WindowManagerPolicy.java的systemReady()方法
[java] view plain copy
  1. public void systemReady() {  
  2.         mPolicy.systemReady();  
  3.     }  
而这个mPolicy 是由PhoneWindowManager.java的构造方法构造出来的;

[java] view plain copy
  1. final WindowManagerPolicy mPolicy = new PhoneWindowManager();  
也就是说最终会调用到PhoneWindowManager.java的systemReady()方法,在这个方法内初始化KeyguardServiceDelegate对象并调用systemReady()方法;

[java] view plain copy
  1. mKeyguardDelegate = new KeyguardServiceDelegate(mContext);  
  2. mKeyguardDelegate.onSystemReady();  
在KeyguardServiceDelegate.java类内,继续调用KeyguardServiceWrapper.java的systemReady()方法;

[java] view plain copy
  1. public void onSystemReady() {  
  2.         if (mKeyguardService != null) {  
  3.             mKeyguardService.onSystemReady();  
  4.         } else {  
  5.             mKeyguardState.systemIsReady = true;  
  6.         }  
  7.     }  
在KeyguardServiceWrapper.java内使用aidl调用KeyguardService.java的onSystemReady()方法;

[java] view plain copy
  1. @Override // Binder interface  
  2. public void onSystemReady() {  
  3.     try {  
  4.         mService.onSystemReady();  
  5.     } catch (RemoteException e) {  
  6.         Slog.w(TAG , "Remote Exception", e);  
  7.     }  
  8. }  
在KeyguardService.java内调用KeyguardViewMediator.java的onSystemReady()方法;
[java] view plain copy
  1. @Override // Binder interface  
  2. public void onSystemReady() {  
  3.     checkPermission();  
  4.     mKeyguardViewMediator.onSystemReady();  
  5. }  

最终在KeyguardViewMediator.java的onSystemReady()方法内调用doKeyguardLocked()开始锁屏加载流程;

[java] view plain copy
  1. /** 
  2.  * Let us know that the system is ready after startup. 
  3.  */  
  4. public void onSystemReady() {  
  5.     mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);  
  6.     synchronized (this) {  
  7.         if (DEBUG) Log.d(TAG, "onSystemReady");  
  8.         mSystemReady = true;  
  9.         doKeyguardLocked(null);  
  10.         mUpdateMonitor.registerCallback(mUpdateCallback);  
  11.     }  
  12.     // Most services aren't available until the system reaches the ready state, so we  
  13.     // send it here when the device first boots.  
  14.     maybeSendUserPresentBroadcast();  
  15. }  
KeyguardViewMediator.java的doKeyguardLocked()方法;

[java] view plain copy
  1. /** 
  2.  * Enable the keyguard if the settings are appropriate. 
  3.  */  
  4. private void doKeyguardLocked(Bundle options) {  
  5.     // if another app is disabling us, don't show  
  6.     if (!mExternallyEnabled) {  
  7.         return;  
  8.     }  
  9.   
  10.     // if the keyguard is already showing, don't bother  
  11.     if (mStatusBarKeyguardViewManager.isShowing()) {  
  12.         resetStateLocked();  
  13.         return;  
  14.     }  
  15.   
  16.     // if the setup wizard hasn't run yet, don't show  
  17.     final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim"false);  
  18.     final boolean absent = SubscriptionManager.isValidSubscriptionId(  
  19.             mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT));  
  20.     final boolean disabled = SubscriptionManager.isValidSubscriptionId(  
  21.             mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));  
  22.     final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()  
  23.             || ((absent || disabled) && requireSim);  
  24.   
  25.     if (!lockedOrMissing && shouldWaitForProvisioning()) {  
  26.         return;  
  27.     }  
  28.   
  29.     if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())  
  30.             && !lockedOrMissing) {  
  31.         return;  
  32.     }  
  33.   
  34.     if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {  
  35.         // Without this, settings is not enabled until the lock screen first appears  
  36.         setShowingLocked(false);  
  37.         hideLocked();  
  38.         mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();  
  39.         return;  
  40.     }  
  41.     showLocked(options);  
  42. }  
1、mExternallyEnabled;默认为true,如果其它应用设置keyguard不显示,则直接return不显示;
2、如果keyguard当前正在显示,则不用管它,重置;
3、如果安装向导未执行完毕,即设备未完成初始化绑定等操作,也不去显示keyguard;
4、如果当前屏幕为灭屏状态,也不去显示keyguard;
5、Without this, settings is not enabled until the lock screen first appears(我这边没有比较好的说法);
6、如果上述条件都不满足则使用showLocked()方法开始显示keyguard。


发送msg为SHOW的消息,开始显示keyguard;

[java] view plain copy
  1. /** 
  2.  * Send message to keyguard telling it to show itself 
  3.  * @see #handleShow 
  4.  */  
  5. private void showLocked(Bundle options) {  
  6.     if (DEBUG) Log.d(TAG, "showLocked");  
  7.     // ensure we stay awake until we are finished displaying the keyguard  
  8.     mShowKeyguardWakeLock.acquire();  
  9.     Message msg = mHandler.obtainMessage(SHOW, options);  
  10.     mHandler.sendMessage(msg);  
  11. }  
调用handleShow()方法;

[java] view plain copy
  1. case SHOW:  
  2.     handleShow((Bundle) msg.obj);  
  3.     break;  
在handleShow()方法中调用StatusBarKeyguardViewManager.java的show()方法;

[java] view plain copy
  1. /** 
  2.  * Handle message sent by {@link #showLocked}. 
  3.  * @see #SHOW 
  4.  */  
  5. private void handleShow(Bundle options) {  
  6.     synchronized (KeyguardViewMediator.this) {  
  7.         if (!mSystemReady) {  
  8.             if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");  
  9.             return;  
  10.         } else {  
  11.             if (DEBUG) Log.d(TAG, "handleShow");  
  12.         }  
  13.   
  14.         setShowingLocked(true);  
  15.         mStatusBarKeyguardViewManager.show(options);  
  16.         mHiding = false;  
  17.         mWakeAndUnlocking = false;  
  18.         resetKeyguardDonePendingLocked();  
  19.         mHideAnimationRun = false;  
  20.         updateActivityLockScreenState();  
  21.         adjustStatusBarLocked();  
  22.         userActivity();  
  23.   
  24.         mShowKeyguardWakeLock.release();  
  25.     }  
  26.     mKeyguardDisplayManager.show();  
  27. }  
调入到StatusBarKeyguardViewManager.java的show()方法

[java] view plain copy
  1. public void show(Bundle options) {  
  2.     mShowing = true;  
  3.     mStatusBarWindowManager.setKeyguardShowing(true);  
  4.     mScrimController.abortKeyguardFadingOut();  
  5.     reset();  
  6. }  
StatusBarKeyguardViewManager.java负责keyguard在status bar中创建、显示、隐藏、重置
StatusBarWindowManager.java负责所有的status bar窗口状态的逻辑管理
1、StatusBarKeyguardViewManager.java的setKeyguardShowing()方法去使用apply()方法刷新mStatusBarView的flag参数;
[java] view plain copy
  1. public void setKeyguardShowing(boolean showing) {  
  2.     mCurrentState.keyguardShowing = showing;  
  3.     apply(mCurrentState);  
  4. }  
2、调用reset()方法去重置mStatusBarView的state,先来看reset()方法;

[java] view plain copy
  1. /** 
  2.  * Reset the state of the view. 
  3.  */  
  4. public void reset() {  
  5.     if (mShowing) {  
  6.         if (mOccluded) {  
  7.             mPhoneStatusBar.hideKeyguard();  
  8.             mPhoneStatusBar.stopWaitingForKeyguardExit();  
  9.             mBouncer.hide(false /* destroyView */);  
  10.         } else {  
  11.             showBouncerOrKeyguard();  
  12.         }  
  13.         KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();  
  14.         updateStates();  
  15.     }  
  16. }  
在reset()方法中会去判断keyguard是否被其它的窗口中断mOccluded,是则不显示keyguard;否则的就执行showBouncerOrKeyguard()方法;
showBouncerOrKeyguard()方法使用KeyguardBouncer.java的needsFullscreenBouncer()方法判断显示常规锁屏还是Bouncer安全锁屏(比如图案锁屏、密码锁屏、PIN码锁屏等);

[java] view plain copy
  1. /** 
  2.  * Shows the notification keyguard or the bouncer depending on 
  3.  * {@link KeyguardBouncer#needsFullscreenBouncer()}. 
  4.  */  
  5. private void showBouncerOrKeyguard() {  
  6.     if (mBouncer.needsFullscreenBouncer()) {  
  7.   
  8.         // The keyguard might be showing (already). So we need to hide it.  
  9.         mPhoneStatusBar.hideKeyguard();  
  10.         mBouncer.show(true /* resetSecuritySelection */);  
  11.     } else {  
  12.         mPhoneStatusBar.showKeyguard();  
  13.         mBouncer.hide(false /* destroyView */);  
  14.         mBouncer.prepare();  
  15.     }  
  16. }  
1、常规锁屏即为滑动锁屏界面,一般滑动即可解锁,称之为notification keyguard;这个类型的keyguard已经和statusbar融为一体了,可以通过PhoneStatusBar.java的对象直接进行控制;
2、Bouncer安全锁屏;比如密码、图案、PIM码、PUK码等锁屏方式的锁屏界面,通过KeyguardBouncer.java来开始控制show()和hide();
[java] view plain copy
  1. KeyguardBouncer.java的show()方法:  
  2.     public void show(boolean resetSecuritySelection) {  
  3.         ensureView();  
  4.         if (resetSecuritySelection) {  
  5.             // showPrimarySecurityScreen() updates the current security method. This is needed in  
  6.             // case we are already showing and the current security method changed.  
  7.             mKeyguardView.showPrimarySecurityScreen();  
  8.         }  
  9.         if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {  
  10.             return;  
  11.         }  
  12.   
  13.         // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole  
  14.         // Keyguard. If we need to authenticate, show the bouncer.  
  15.         if (!mKeyguardView.dismiss()) {  
  16.             mShowingSoon = true;  
  17.   
  18.             // Split up the work over multiple frames.  
  19.             DejankUtils.postAfterTraversal(mShowRunnable);  
  20.         }  
  21.     }  
1、首先调用ensureView()方法去加载keyguard_bouncer view

[java] view plain copy
  1. private void ensureView() {  
  2.     if (mRoot == null) {  
  3.         inflateView();  
  4.     }  
  5. }  
  6.   
  7. private void inflateView() {  
  8.     removeView();  
  9.     mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);  
  10.     mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);  
  11.     mKeyguardView.setLockPatternUtils(mLockPatternUtils);  
  12.     mKeyguardView.setViewMediatorCallback(mCallback);  
  13.     mContainer.addView(mRoot, mContainer.getChildCount());  
  14.     mRoot.setVisibility(View.INVISIBLE);  
  15.     mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);  
  16. }  
2、调用KeyguardHostView.java的showPrimarySecurityScreen()方法;

[java] view plain copy
  1. /** 
  2.  * Called when the view needs to be shown. 
  3.  */  
  4. public void showPrimarySecurityScreen() {  
  5.     if (DEBUG) Log.d(TAG, "show()");  
  6.     mSecurityContainer.showPrimarySecurityScreen(false);  
  7. }  
继续调用KeyguardSecurityContainer.java的showPrimarySecurityScreen()方法,先去获取锁屏方式;

[java] view plain copy
  1. /** 
  2.  * Shows the primary security screen for the user. This will be either the multi-selector 
  3.  * or the user's security method. 
  4.  * @param turningOff true if the device is being turned off 
  5.  */  
  6. void showPrimarySecurityScreen(boolean turningOff) {  
  7.     SecurityMode securityMode = mSecurityModel.getSecurityMode();  
  8.     if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");  
  9.     showSecurityScreen(securityMode);  
  10. }  
继续往下将获取到的锁屏方式securityMode作为参数调用showSecurityScreen()方法;这个方法主要是用来根据securityMode显示锁屏view的。
[java] view plain copy
  1. /** 
  2.  * Switches to the given security view unless it's already being shown, in which case 
  3.  * this is a no-op. 
  4.  * 
  5.  * @param securityMode 
  6.  */  
  7. private void showSecurityScreen(SecurityMode securityMode) {  
  8.     if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");  
  9.   
  10.     if (securityMode == mCurrentSecuritySelection) return;  
  11.   
  12.     KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);  
  13.     KeyguardSecurityView newView = getSecurityView(securityMode);  
  14.   
  15.     // Emulate Activity life cycle  
  16.     if (oldView != null) {  
  17.         oldView.onPause();  
  18.         oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view  
  19.     }  
  20.     if (securityMode != SecurityMode.None) {  
  21.         newView.onResume(KeyguardSecurityView.VIEW_REVEALED);  
  22.         newView.setKeyguardCallback(mCallback);  
  23.     }  
  24.   
  25.     // Find and show this child.  
  26.     final int childCount = mSecurityViewFlipper.getChildCount();  
  27.   
  28.     final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);  
  29.     for (int i = 0; i < childCount; i++) {  
  30.         if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {  
  31.             mSecurityViewFlipper.setDisplayedChild(i);  
  32.             break;  
  33.         }  
  34.     }  
  35.   
  36.     mCurrentSecuritySelection = securityMode;  
  37.     mSecurityCallback.onSecurityModeChanged(securityMode,  
  38.             securityMode != SecurityMode.None && newView.needsInput());  
  39. }  
1、首先判断传入进来的securityMode是否已经被显示;
2、调用getSecurityView()方法获取给定的锁屏view;
3、调用KeyguardSecurityView.java的onPause()方法暂停显示旧锁屏view,onResume()方法开始显示新的锁屏view;KeyguardSecurityView.java是一个接口类,其内部方法都是抽象的只有声明没有实现,其方法实现都是在继承于这个接口的类中。
而在keyguard中主要是KeyguardAbsKeyInputView.java、KeyguardPasswordView.java、KeyguardPatternView.java等等这些类继承于此接口实现其内部方法,这些类就是具体的锁屏界面view显示;


开机显示keyguard的总结:
1、在KeyguardViewMediator.java的onSystemReady()方法内调用doKeyguardLocked()开始锁屏加载流程;
2、setKeyguardEnabled();其他应用程序或者服务可以调用setKeyguardEnabled()方法请求禁止锁屏;
3、KeyguardViewMediator.java在keyguard中起着主要调度的作用,主要负责
1)查询锁屏状态,当前是锁屏还是解锁状态;在锁屏状态下,会限制输入事件。
2)PhoneWindowManager.java通过mKeyguardDelegate对象(KeyguardServiceDelegate.java)来使能KeyguardViewMediator.java,调用其中的方法;
3)响应SIM卡状态变化并对锁屏界面做相应的调整onSimStateChanged();
4、判断keyguard是否被禁止、keyguard当前是否正在显示等等即当前是否可以显示keguard,可以显示的话继续调用showLocked()方法;
5、调用handleShow()方法,调用StatusBarKeyguardViewManager.java的show()开始显示keyguard锁屏界面;
6、调用reset()方法,调用showBouncerOrKeyguard()方法判断是显示正常锁屏界面还是安全锁屏界面;显示正常锁屏的话直接调用PhoneStatusBar.java的showKeyguard()或者hideKeyguard()方法;如果显示安全锁屏界面的话则调入KeyguardBouncer.java类内;
7、调用KeyguardBouncer.java的show()方法;使用ensureView()方法去加载实例化布局;调用KeyguardHostView.java的showPrimarySecurityScreen()方法去显示安全锁屏界面;
8、KeyguardHostView.java的showPrimarySecurityScreen()方法会调入到KeyguardSecurityContainer.java的showPrimarySecurityScreen()方法中来;
9、调用showSecurityScreen()方法,根据锁屏方式来加载不同的锁屏view;
10、KeyguardSecurityView.java是一个接口类,其内部方法都是抽象的只有声明没有实现,其方法实现都是在继承于这个接口的类中。
而在keyguard中主要是KeyguardAbsKeyInputView.java、KeyguardPasswordView.java、KeyguardPatternView.java等等Keyguard*View.java这些类继承于此接口实现其内部方法,这些类就是具体的锁屏界面view显示;


系统灭屏Screen off之后的keguard加载流程:
android系统中的自动灭屏跟Power按键之后灭屏流程可能有点区别,但是由于主要是分析灭屏之后keyguard加载,所以只需要关心keguard在系统灭屏之后的加载流程。
这里以按power键灭屏为例,分析其流程:
当亮屏状态下Power键按下之后,经过一系列的判断之后会调用mPowerManager.goToSleep()方法,即通过aidl调用到PowerManagerService.java的gotoSleep()方法:

[java] view plain copy
  1. @Override // Binder call  
  2. public void goToSleep(long eventTime, int reason, int flags) {  
  3.     if (eventTime > SystemClock.uptimeMillis()) {  
  4.         throw new IllegalArgumentException("event time must not be in the future");  
  5.     }  
  6.   
  7.     mContext.enforceCallingOrSelfPermission(  
  8.             android.Manifest.permission.DEVICE_POWER, null);  
  9.   
  10.     final int uid = Binder.getCallingUid();  
  11.     final long ident = Binder.clearCallingIdentity();  
  12.     try {  
  13.         goToSleepInternal(eventTime, reason, flags, uid);  
  14.     } finally {  
  15.         Binder.restoreCallingIdentity(ident);  
  16.     }  
  17. }  
继续调用goToSleepInternal()方法:

[java] view plain copy
  1. private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {  
  2.     synchronized (mLock) {  
  3.         if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {  
  4.             updatePowerStateLocked();  
  5.         }  
  6.     }  
  7. }  
调用updatePowerStateLocked()方法,在这个方法内又去调用finishWakefulnessChangeIfNeededLocked()方法

[java] view plain copy
  1. private void finishWakefulnessChangeIfNeededLocked() {  
  2.     if (mWakefulnessChanging && mDisplayReady) {  
  3.         if (mWakefulness == WAKEFULNESS_DOZING  
  4.                 && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {  
  5.             return// wait until dream has enabled dozing  
  6.         }  
  7.         mWakefulnessChanging = false;  
  8.         mNotifier.onWakefulnessChangeFinished();  
  9.     }  
  10. }  
此时调用Notifier.java的onWakefulnessChangeFinished()方法:

[java] view plain copy
  1. /** 
  2.  * Notifies that the device has finished changing wakefulness. 
  3.  */  
  4. public void onWakefulnessChangeFinished() {  
  5.     if (DEBUG) {  
  6.         Slog.d(TAG, "onWakefulnessChangeFinished");  
  7.     }  
  8.   
  9.     if (mInteractiveChanging) {  
  10.         mInteractiveChanging = false;  
  11.         handleLateInteractiveChange();  
  12.     }  
  13. }  
调用handleLateInteractiveChange()方法;

[java] view plain copy
  1. /** 
  2.  * Handle late interactive state changes once they are finished so that the system can 
  3.  * finish pending transitions (such as turning the screen off) before causing 
  4.  * applications to change state visibly. 
  5.  */  
  6. private void handleLateInteractiveChange() {  
  7.     synchronized (mLock) {  
  8.         if (mInteractive) {  
  9.             // Finished waking up...  
  10.             mHandler.post(new Runnable() {  
  11.                 @Override  
  12.                 public void run() {  
  13.                     mPolicy.finishedWakingUp();  
  14.                 }  
  15.             });  
  16.         } else {  
  17.             // Finished going to sleep...  
  18.             // This is a good time to make transitions that we don't want the user to see,  
  19.             // such as bringing the key guard to focus.  There's no guarantee for this  
  20.             // however because the user could turn the device on again at any time.  
  21.             // Some things may need to be protected by other mechanisms that defer screen on.  
  22.   
  23.             // Cancel pending user activity.  
  24.             if (mUserActivityPending) {  
  25.                 mUserActivityPending = false;  
  26.                 mHandler.removeMessages(MSG_USER_ACTIVITY);  
  27.             }  
  28.   
  29.             // Tell the policy we finished going to sleep.  
  30.             final int why = translateOffReason(mInteractiveChangeReason);  
  31.             mHandler.post(new Runnable() {  
  32.                 @Override  
  33.                 public void run() {  
  34.                     EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 00);  
  35.                     mPolicy.finishedGoingToSleep(why);  
  36.                 }  
  37.             });  
  38.   
  39.             // Send non-interactive broadcast.  
  40.             mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;  
  41.             mPendingGoToSleepBroadcast = true;  
  42.             updatePendingBroadcastLocked();  
  43.         }  
  44.     }  
  45. }  
这个方法里面需要关注的有两句话:mPolicy.finishedWakingUp()和mPolicy.finishedGoingToSleep();看其中的注释发现一个是唤醒另外一个是睡眠操作,由于当前是power灭屏,所以需要看得是mPolicy.finishedGoingToSleep()方法。而mPolicy是WindowManagerPolicy.java的对象,这个类又是一个接口类,接口实现是在PhoneWindowManager.java类中,故此时调入到PhoneWindowManager.java的finishedGoingToSleep()方法;

[java] view plain copy
  1. // Called on the PowerManager's Notifier thread.  
  2. @Override  
  3. public void finishedGoingToSleep(int why) {  
  4.     EventLog.writeEvent(700000);  
  5.     if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");  
  6.     MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);  
  7.   
  8.     // We must get this work done here because the power manager will drop  
  9.     // the wake lock and let the system suspend once this function returns.  
  10.     synchronized (mLock) {  
  11.         mAwake = false;  
  12.         updateWakeGestureListenerLp();  
  13.         updateOrientationListenerLp();  
  14.         updateLockScreenTimeout();  
  15.     }  
  16.     if (mKeyguardDelegate != null) {  
  17.         mKeyguardDelegate.onFinishedGoingToSleep(why);  
  18.     }  
  19. }  
分析这个方法看到这么一句话:

[java] view plain copy
  1. mKeyguardDelegate.onFinishedGoingToSleep(why);  
也就是说会调用KeyguardServiceDelegate.java的onFinishedGoingToSleep()方法;而在上面的分析过程中知道,PhoneWindowManager.java通过mKeyguardDelegate对象(KeyguardServiceDelegate.java)来使能KeyguardViewMediator.java,调用其中的方法;也就是说通过这句话此时逻辑已经调入到了KeyguardViewMediator.java类的onFinishedGoingToSleep()方法。

[java] view plain copy
  1. public void onFinishedGoingToSleep(int why) {  
  2.     if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")");  
  3.     synchronized (this) {  
  4.         mDeviceInteractive = false;  
  5.         mGoingToSleep = false;  
  6.   
  7.         resetKeyguardDonePendingLocked();  
  8.         mHideAnimationRun = false;  
  9.   
  10.         notifyFinishedGoingToSleep();  
  11.   
  12.         if (mPendingReset) {  
  13.             resetStateLocked();  
  14.             mPendingReset = false;  
  15.         }  
  16.         if (mPendingLock) {  
  17.             doKeyguardLocked(null);  
  18.             mPendingLock = false;  
  19.         }  
  20.     }  
  21.     KeyguardUpdateMonitor.getInstance(mContext).dispatchFinishedGoingToSleep(why);  
  22. }  

在这个方法中调用notifyFinishedGoingToSleep()方法,向mHandler中发送一个msg为NOTIFY_FINISHED_GOING_TO_SLEEP的消息;

[java] view plain copy
  1. private void notifyFinishedGoingToSleep() {  
  2.     if (DEBUG) Log.d(TAG, "notifyFinishedGoingToSleep");  
  3.     mHandler.sendEmptyMessage(NOTIFY_FINISHED_GOING_TO_SLEEP);  
  4. }  
mHandler收到这个消息后,去调用handleNotifyFinishedGoingToSleep()方法;

[java] view plain copy
  1. case NOTIFY_FINISHED_GOING_TO_SLEEP:  
  2.     handleNotifyFinishedGoingToSleep();  
  3.     break;  
在这个方法中去调用StatusBarKeyguardViewManager.java的onFinishedGoingToSleep()方法;

[java] view plain copy
  1. private void handleNotifyFinishedGoingToSleep() {  
  2.     synchronized (KeyguardViewMediator.this) {  
  3.         if (DEBUG) Log.d(TAG, "handleNotifyFinishedGoingToSleep");  
  4.         mStatusBarKeyguardViewManager.onFinishedGoingToSleep();  
  5.     }  
  6. }  
再来看StatusBarKeyguardViewManager.java的onFinishedGoingToSleep()方法:
[java] view plain copy
  1. public void onFinishedGoingToSleep() {  
  2.     mDeviceInteractive = false;  
  3.     mPhoneStatusBar.onFinishedGoingToSleep();  
  4.     mBouncer.onScreenTurnedOff();  
  5. }  
1、调用PhoneStatusBar.java的onFinishedGoingToSleep(),去通知PhoneStatusBar更新当前的状态;
2、进入KeyguardBouncer.java的onScreenTurnedOff()方法真正开始keyguard的加载;


接下来来看KeyguardBouncer.java的onScreenTurnedOff()方法:

[java] view plain copy
  1. public void onScreenTurnedOff() {  
  2.     if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {  
  3.         mKeyguardView.onPause();  
  4.     }  
  5. }  
调用KeyguardHostView.java的onPause()方法:
[java] view plain copy
  1. /** 
  2.  * Called when the Keyguard is not actively shown anymore on the screen. 
  3.  */  
  4. public void onPause() {  
  5.     if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",  
  6.             Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));  
  7.     mSecurityContainer.showPrimarySecurityScreen(true);  
  8.     mSecurityContainer.onPause();  
  9.     clearFocus();  
  10. }  
继续调用KeyguardSecurityContainer.java的showPrimarySecurityScreen()方法,根据上面的分析知道,此处先会去获取当前锁屏方式,然后根据得到的锁屏方式去加载锁屏界面;
至此完成keyguard在screen off状态下的加载流程分析;


正常灭屏显示keyguard流程总结:
1、不管是按Power键还是自动灭屏,都会执行到PowerManagerService.java的gotoSleep()方法;
2、在这个方法内通过一系列的调用,调入到PhoneWindowManager.java的finishedGoingToSleep()方法;
3、在PhoneWindowManager.java类中通过KeyguardServiceDelegate.java类的对象mKeyguardDelegate来使能KeyguardViewMediator.java;
4、而KeyguardViewMediator.java作为keyguard的调度者,从这里开始keyguard的加载;
5、最终在KeyguardSecurityContainer.java的showPrimarySecurityScreen()方法内去实现根据锁屏方式加载锁屏界面;


原文地址: http://blog.csdn.net/Otaku_627/article/details/53769473?locationNum=5&fps=1