锁屏界面的加载通常在android中有两种方式触发:android系统开机和screenOff(灭屏)后,再screenOn;
先来看
android系统开机时候的锁屏加载流程 : 首先在系统启动过程中,会进入到SystemServer.java的startOtherServices()方法:
初始化WindowManagerService;
wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore);
调用systemReady()方法,表示系统准备启动;
try { wm.systemReady(); } catch (Throwable e) { reportWtf("making Window Manager Service ready" , e); }
调用WindowManagerPolicy.java的systemReady()方法
public void systemReady() { mPolicy.systemReady(); }
而这个mPolicy 是由PhoneWindowManager.java的构造方法构造出来的;
final WindowManagerPolicy mPolicy = new PhoneWindowManager();
也就是说最终会调用到PhoneWindowManager.java的systemReady()方法,在这个方法内初始化KeyguardServiceDelegate对象并调用systemReady()方法;
mKeyguardDelegate = new KeyguardServiceDelegate(mContext); mKeyguardDelegate.onSystemReady();
在KeyguardServiceDelegate.java类内,继续调用KeyguardServiceWrapper.java的systemReady()方法;
public void onSystemReady() { if (mKeyguardService != null ) { mKeyguardService.onSystemReady(); } else { mKeyguardState.systemIsReady = true ; } }
在KeyguardServiceWrapper.java内使用aidl调用KeyguardService.java的onSystemReady()方法;
@Override public void onSystemReady() { try { mService.onSystemReady(); } catch (RemoteException e) { Slog.w(TAG , "Remote Exception" , e); } }
在KeyguardService.java内调用KeyguardViewMediator.java的onSystemReady()方法;
@Override public void onSystemReady() { checkPermission(); mKeyguardViewMediator.onSystemReady(); }
最终在KeyguardViewMediator.java的onSystemReady()方法内调用doKeyguardLocked()开始锁屏加载流程;
public void onSystemReady() { mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); synchronized ( this ) { if (DEBUG) Log.d(TAG, "onSystemReady" ); mSystemReady = true ; doKeyguardLocked(null ); mUpdateMonitor.registerCallback(mUpdateCallback); } maybeSendUserPresentBroadcast(); }
KeyguardViewMediator.java的doKeyguardLocked()方法;
private void doKeyguardLocked(Bundle options) { if (!mExternallyEnabled) { return ; } if (mStatusBarKeyguardViewManager.isShowing()) { resetStateLocked(); return ; } final boolean requireSim = !SystemProperties.getBoolean( "keyguard.no_require_sim" , false ); final boolean absent = SubscriptionManager.isValidSubscriptionId( mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT)); final boolean disabled = SubscriptionManager.isValidSubscriptionId( mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED)); final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure() || ((absent || disabled) && requireSim); if (!lockedOrMissing && shouldWaitForProvisioning()) { return ; } if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing) { return ; } if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) { setShowingLocked(false ); hideLocked(); mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt(); return ; } showLocked(options); }
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;
private void showLocked(Bundle options) { if (DEBUG) Log.d(TAG, "showLocked" ); mShowKeyguardWakeLock.acquire(); Message msg = mHandler.obtainMessage(SHOW, options); mHandler.sendMessage(msg); }
调用handleShow()方法;
case SHOW: handleShow((Bundle) msg.obj); break ;
在handleShow()方法中调用StatusBarKeyguardViewManager.java的show()方法;
private void handleShow(Bundle options) { synchronized (KeyguardViewMediator. this ) { if (!mSystemReady) { if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready." ); return ; } else { if (DEBUG) Log.d(TAG, "handleShow" ); } setShowingLocked(true ); mStatusBarKeyguardViewManager.show(options); mHiding = false ; mWakeAndUnlocking = false ; resetKeyguardDonePendingLocked(); mHideAnimationRun = false ; updateActivityLockScreenState(); adjustStatusBarLocked(); userActivity(); mShowKeyguardWakeLock.release(); } mKeyguardDisplayManager.show(); }
调入到StatusBarKeyguardViewManager.java的show()方法
public void show(Bundle options) { mShowing = true ; mStatusBarWindowManager.setKeyguardShowing(true ); mScrimController.abortKeyguardFadingOut(); reset(); }
StatusBarKeyguardViewManager.java负责keyguard在status bar中创建、显示、隐藏、重置
StatusBarWindowManager.java负责所有的status bar窗口状态的逻辑管理
1、StatusBarKeyguardViewManager.java的setKeyguardShowing()方法去使用apply()方法刷新mStatusBarView的flag参数;
public void setKeyguardShowing( boolean showing) { mCurrentState.keyguardShowing = showing; apply(mCurrentState); }
2、调用reset()方法去重置mStatusBarView的state,先来看reset()方法;
public void reset() { if (mShowing) { if (mOccluded) { mPhoneStatusBar.hideKeyguard(); mPhoneStatusBar.stopWaitingForKeyguardExit(); mBouncer.hide(false ); } else { showBouncerOrKeyguard(); } KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); updateStates(); } }
在reset()方法中会去判断keyguard是否被其它的窗口中断mOccluded,是则不显示keyguard;否则的就执行showBouncerOrKeyguard()方法;
showBouncerOrKeyguard()方法使用KeyguardBouncer.java的needsFullscreenBouncer()方法判断显示常规锁屏还是Bouncer安全锁屏(比如图案锁屏、密码锁屏、PIN码锁屏等);
private void showBouncerOrKeyguard() { if (mBouncer.needsFullscreenBouncer()) { mPhoneStatusBar.hideKeyguard(); mBouncer.show(true ); } else { mPhoneStatusBar.showKeyguard(); mBouncer.hide(false ); mBouncer.prepare(); } }
1、常规锁屏即为滑动锁屏界面,一般滑动即可解锁,称之为notification keyguard;这个类型的keyguard已经和statusbar融为一体了,可以通过PhoneStatusBar.java的对象直接进行控制;
2、Bouncer安全锁屏;比如密码、图案、PIM码、PUK码等锁屏方式的锁屏界面,通过KeyguardBouncer.java来开始控制show()和hide();
KeyguardBouncer.java的show()方法: public void show( boolean resetSecuritySelection) { ensureView(); if (resetSecuritySelection) { mKeyguardView.showPrimarySecurityScreen(); } if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) { return ; } if (!mKeyguardView.dismiss()) { mShowingSoon = true ; DejankUtils.postAfterTraversal(mShowRunnable); } }
1、首先调用ensureView()方法去加载keyguard_bouncer view
private void ensureView() { if (mRoot == null ) { inflateView(); } } private void inflateView() { removeView(); mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null ); mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view); mKeyguardView.setLockPatternUtils(mLockPatternUtils); mKeyguardView.setViewMediatorCallback(mCallback); mContainer.addView(mRoot, mContainer.getChildCount()); mRoot.setVisibility(View.INVISIBLE); mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME); }
2、调用KeyguardHostView.java的showPrimarySecurityScreen()方法;
public void showPrimarySecurityScreen() { if (DEBUG) Log.d(TAG, "show()" ); mSecurityContainer.showPrimarySecurityScreen(false ); }
继续调用KeyguardSecurityContainer.java的showPrimarySecurityScreen()方法,先去获取锁屏方式;
void showPrimarySecurityScreen( boolean turningOff) { SecurityMode securityMode = mSecurityModel.getSecurityMode(); if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")" ); showSecurityScreen(securityMode); }
继续往下将获取到的锁屏方式securityMode作为参数调用showSecurityScreen()方法;这个方法主要是用来根据securityMode显示锁屏view的。
private void showSecurityScreen(SecurityMode securityMode) { if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")" ); if (securityMode == mCurrentSecuritySelection) return ; KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection); KeyguardSecurityView newView = getSecurityView(securityMode); if (oldView != null ) { oldView.onPause(); oldView.setKeyguardCallback(mNullCallback); } if (securityMode != SecurityMode.None) { newView.onResume(KeyguardSecurityView.VIEW_REVEALED); newView.setKeyguardCallback(mCallback); } final int childCount = mSecurityViewFlipper.getChildCount(); final int securityViewIdForMode = getSecurityViewIdForMode(securityMode); for ( int i = 0 ; i < childCount; i++) { if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) { mSecurityViewFlipper.setDisplayedChild(i); break ; } } mCurrentSecuritySelection = securityMode; mSecurityCallback.onSecurityModeChanged(securityMode, securityMode != SecurityMode.None && newView.needsInput()); }
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()方法:
@Override public void goToSleep( long eventTime, int reason, int flags) { if (eventTime > SystemClock.uptimeMillis()) { throw new IllegalArgumentException( "event time must not be in the future" ); } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null ); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { goToSleepInternal(eventTime, reason, flags, uid); } finally { Binder.restoreCallingIdentity(ident); } }
继续调用goToSleepInternal()方法:
private void goToSleepInternal( long eventTime, int reason, int flags, int uid) { synchronized (mLock) { if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) { updatePowerStateLocked(); } } }
调用updatePowerStateLocked()方法,在这个方法内又去调用finishWakefulnessChangeIfNeededLocked()方法
private void finishWakefulnessChangeIfNeededLocked() { if (mWakefulnessChanging && mDisplayReady) { if (mWakefulness == WAKEFULNESS_DOZING && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0 ) { return ; } mWakefulnessChanging = false ; mNotifier.onWakefulnessChangeFinished(); } }
此时调用Notifier.java的onWakefulnessChangeFinished()方法:
public void onWakefulnessChangeFinished() { if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeFinished" ); } if (mInteractiveChanging) { mInteractiveChanging = false ; handleLateInteractiveChange(); } }
调用handleLateInteractiveChange()方法;
private void handleLateInteractiveChange() { synchronized (mLock) { if (mInteractive) { mHandler.post(new Runnable() { @Override public void run() { mPolicy.finishedWakingUp(); } }); } else { if (mUserActivityPending) { mUserActivityPending = false ; mHandler.removeMessages(MSG_USER_ACTIVITY); } final int why = translateOffReason(mInteractiveChangeReason); mHandler.post(new Runnable() { @Override public void run() { EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0 , why, 0 , 0 ); mPolicy.finishedGoingToSleep(why); } }); mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP; mPendingGoToSleepBroadcast = true ; updatePendingBroadcastLocked(); } } }
这个方法里面需要关注的有两句话:mPolicy.finishedWakingUp()和mPolicy.finishedGoingToSleep();看其中的注释发现一个是唤醒另外一个是睡眠操作,由于当前是power灭屏,所以需要看得是mPolicy.finishedGoingToSleep()方法。而mPolicy是WindowManagerPolicy.java的对象,这个类又是一个接口类,接口实现是在PhoneWindowManager.java类中,故此时调入到PhoneWindowManager.java的finishedGoingToSleep()方法;
@Override public void finishedGoingToSleep( int why) { EventLog.writeEvent(70000 , 0 ); if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")" ); MetricsLogger.histogram(mContext, "screen_timeout" , mLockScreenTimeout / 1000 ); synchronized (mLock) { mAwake = false ; updateWakeGestureListenerLp(); updateOrientationListenerLp(); updateLockScreenTimeout(); } if (mKeyguardDelegate != null ) { mKeyguardDelegate.onFinishedGoingToSleep(why); } }
分析这个方法看到这么一句话:
mKeyguardDelegate.onFinishedGoingToSleep(why);
也就是说会调用KeyguardServiceDelegate.java的onFinishedGoingToSleep()方法;而在上面的分析过程中知道,PhoneWindowManager.java通过mKeyguardDelegate对象(KeyguardServiceDelegate.java)来使能KeyguardViewMediator.java,调用其中的方法;也就是说通过这句话此时逻辑已经调入到了KeyguardViewMediator.java类的onFinishedGoingToSleep()方法。
public void onFinishedGoingToSleep( int why) { if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")" ); synchronized ( this ) { mDeviceInteractive = false ; mGoingToSleep = false ; resetKeyguardDonePendingLocked(); mHideAnimationRun = false ; notifyFinishedGoingToSleep(); if (mPendingReset) { resetStateLocked(); mPendingReset = false ; } if (mPendingLock) { doKeyguardLocked(null ); mPendingLock = false ; } } KeyguardUpdateMonitor.getInstance(mContext).dispatchFinishedGoingToSleep(why); }
在这个方法中调用notifyFinishedGoingToSleep()方法,向mHandler中发送一个msg为NOTIFY_FINISHED_GOING_TO_SLEEP的消息;
private void notifyFinishedGoingToSleep() { if (DEBUG) Log.d(TAG, "notifyFinishedGoingToSleep" ); mHandler.sendEmptyMessage(NOTIFY_FINISHED_GOING_TO_SLEEP); }
mHandler收到这个消息后,去调用handleNotifyFinishedGoingToSleep()方法;
case NOTIFY_FINISHED_GOING_TO_SLEEP: handleNotifyFinishedGoingToSleep(); break ;
在这个方法中去调用StatusBarKeyguardViewManager.java的onFinishedGoingToSleep()方法;
private void handleNotifyFinishedGoingToSleep() { synchronized (KeyguardViewMediator. this ) { if (DEBUG) Log.d(TAG, "handleNotifyFinishedGoingToSleep" ); mStatusBarKeyguardViewManager.onFinishedGoingToSleep(); } }
再来看StatusBarKeyguardViewManager.java的onFinishedGoingToSleep()方法:
public void onFinishedGoingToSleep() { mDeviceInteractive = false ; mPhoneStatusBar.onFinishedGoingToSleep(); mBouncer.onScreenTurnedOff(); }
1、调用PhoneStatusBar.java的onFinishedGoingToSleep(),去通知PhoneStatusBar更新当前的状态;
2、进入KeyguardBouncer.java的onScreenTurnedOff()方法真正开始keyguard的加载;
接下来来看KeyguardBouncer.java的onScreenTurnedOff()方法:
public void onScreenTurnedOff() { if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) { mKeyguardView.onPause(); } }
调用KeyguardHostView.java的onPause()方法:
public void onPause() { if (DEBUG) Log.d(TAG, String.format( "screen off, instance %s at %s" , Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); mSecurityContainer.showPrimarySecurityScreen(true ); mSecurityContainer.onPause(); clearFocus(); }
继续调用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