生活随笔
收集整理的這篇文章主要介紹了
Android 7.1.1 锁屏界面启动流程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 前幾天遇到一個低概率復現鎖屏界面不顯示,只顯示狀態欄的問題,跟了下鎖屏界面啟動顯示的流程,在這分享下,也方便以后自己查看。前面簡單介紹了下Zygote啟動流程,?Zygote進程啟動后會首先創建一個SystemServer進程,SystemServer進程在調用startOtherServices同時也會調用WindowManagerService的systemReady()方法
[java]?view plain
?copy ?? private?void?startOtherServices()?{?? ?????...?? ?????wm?=?WindowManagerService.main(context,?inputManager,?? ??????????????????mFactoryTestMode?!=?FactoryTest.FACTORY_TEST_LOW_LEVEL,?? ??????????????????!mFirstBoot,?mOnlyCore);?? ??????...?? ??????try?{?? ??????????wm.systemReady();?? ??????????Slog.i("jason11",?"SystemServer?wm.systemReady");?? ??????}?catch?(Throwable?e)?{?? ??????????reportWtf("making?Window?Manager?Service?ready",?e);?? ??????}?? ??????...?? ??}??
?在WindowManagerService中直接調用了PhoneWindowManager里的systemReady()
[java]?view plain
?copy ?? ?? ??public?void?systemReady()?{?? ??????mPolicy.systemReady();?? ??}??
在
PhoneWindowManager的systemReady()會根據一個Boolean值bindKeyguardNow來決定是否綁定keyguard service
[java]?view plain
?copy ?? ?? ??@Override?? ??public?void?systemReady()?{?? ??????mKeyguardDelegate?=?new?KeyguardServiceDelegate(mContext);?? ??????mKeyguardDelegate.onSystemReady();?? ?? ??????readCameraLensCoverState();?? ??????updateUiMode();?? ??????boolean?bindKeyguardNow;?? ??????synchronized?(mLock)?{?? ??????????updateOrientationListenerLp();?? ??????????mSystemReady?=?true;?? ??????????mHandler.post(new?Runnable()?{?? ??????????????@Override?? ??????????????public?void?run()?{?? ??????????????????updateSettings();?? ??????????????}?? ??????????});?? ?? ??????????bindKeyguardNow?=?mDeferBindKeyguard;?? ??????????if?(bindKeyguardNow)?{?? ???????????????? ??????????????mDeferBindKeyguard?=?false;?? ??????????}?? ??????}?? ??????if?(bindKeyguardNow)?{?? ??????????mKeyguardDelegate.bindService(mContext);?? ??????????mKeyguardDelegate.onBootCompleted();?? ??????}?? ??????mSystemGestures.systemReady();?? ??}??
看到這里,可能會想到如果bindKeyguardNow為false就會不綁定,后面通過繼續跟蹤發現在PhoneWindowManager的systemBooted()里也會去綁定keyguard service,如果在systemBooted里綁定了就不在systemReady里再去綁定,自己測試的時候是在systemBooted綁定的
[java]?view plain
?copy ?? ????? ??@Override?? ??public?void?systemBooted()?{?? ??????boolean?bindKeyguardNow?=?false;?? ??????synchronized?(mLock)?{?? ???????????? ???????????? ??????????if?(mKeyguardDelegate?!=?null)?{?? ??????????????bindKeyguardNow?=?true;?? ??????????}?else?{?? ???????????????? ???????????????? ??????????????mDeferBindKeyguard?=?true;?? ??????????}?? ??????}?? ??????if?(bindKeyguardNow)?{?? ??????????mKeyguardDelegate.bindService(mContext);?? ??????????mKeyguardDelegate.onBootCompleted();?? ??????}?? ??????synchronized?(mLock)?{?? ??????????mSystemBooted?=?true;?? ??????}?? ??????startedWakingUp();?? ??????screenTurningOn(null);?? ??????screenTurnedOn();?? ??}??
下面就通過如下的時序圖看看是如何調用到systemBooted的,就不在一步步跟了
通過上面的分析知道,無論是在systemReady或systemBooted,都調用了KeyguardServiceDelegate對象的bindService方法,下面就以這個方法開始,看看鎖屏界面是怎么顯示出來的,先看看下面的時序圖,再來分步講解
1、先來看看在KeyguardServiceDelegate如何綁定KeyguardService的
[java]?view plain
?copy ?? public?class?KeyguardServiceDelegate?{?? ????...?? ????public?void?bindService(Context?context)?{?? ????????Intent?intent?=?new?Intent();?? ????????final?Resources?resources?=?context.getApplicationContext().getResources();?? ?? ????????final?ComponentName?keyguardComponent?=?ComponentName.unflattenFromString(?? ????????????????resources.getString(com.android.internal.R.string.config_keyguardComponent));?? ????????intent.setComponent(keyguardComponent);?? ?? ????????if?(!context.bindServiceAsUser(intent,?mKeyguardConnection,?? ????????????????Context.BIND_AUTO_CREATE,?UserHandle.OWNER))?{?? ????????????Log.v(TAG,?"***?Keyguard:?can't?bind?to?"?+?keyguardComponent);?? ????????????mKeyguardState.showing?=?false;?? ????????????mKeyguardState.showingAndNotOccluded?=?false;?? ????????????mKeyguardState.secure?=?false;?? ????????????synchronized?(mKeyguardState)?{?? ?????????????????? ?????????????????? ?????????????????? ????????????????mKeyguardState.deviceHasKeyguard?=?false;?? ????????????????hideScrim();?? ????????????}?? ????????}?else?{?? ????????????if?(DEBUG)?Log.v(TAG,?"***?Keyguard?started");?? ????????}?? ????}?? ????...?? }??
在bindService中調用了bindServiceAsUser綁定指定intent的service,config_keyguardComponent的定義如下
[html]?view plain
?copy //frameworks/base/core/res/res/values/config.xml?? ?????? ????<string?name="config_keyguardComponent"?translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>??
當綁定成功后會調用mKeyguardConnection里的onServiceConnected方法
[java]?view plain
?copy ?? public?class?KeyguardServiceDelegate?{?? ????...?? ??????private?final?ServiceConnection?mKeyguardConnection?=?new?ServiceConnection()?{?? ????????@Override?? ????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{?? ????????????if?(DEBUG)?Log.v(TAG,?"***?Keyguard?connected?(yay!)");?? ????????????mKeyguardService?=?new?KeyguardServiceWrapper(mContext,?? ????????????????????IKeyguardService.Stub.asInterface(service));?? ????????????if?(mKeyguardState.systemIsReady)?{?? ?????????????????? ????????????????mKeyguardService.onSystemReady();?? ?????????????????? ????????????????if?(mKeyguardState.interactiveState?==?INTERACTIVE_STATE_AWAKE)?{?? ????????????????????mKeyguardService.onStartedWakingUp();?? ????????????????}?? ????????????????if?(mKeyguardState.screenState?==?SCREEN_STATE_ON?? ????????????????????????||?mKeyguardState.screenState?==?SCREEN_STATE_TURNING_ON)?{?? ????????????????????mKeyguardService.onScreenTurningOn(?? ????????????????????????????new?KeyguardShowDelegate(mDrawnListenerWhenConnect));?? ????????????????}?? ????????????????if?(mKeyguardState.screenState?==?SCREEN_STATE_ON)?{?? ????????????????????mKeyguardService.onScreenTurnedOn();?? ????????????????}?? ????????????????mDrawnListenerWhenConnect?=?null;?? ????????????}?? ????????????if?(mKeyguardState.bootCompleted)?{?? ????????????????mKeyguardService.onBootCompleted();?? ????????????}?? ????????????if?(mKeyguardState.occluded)?{?? ????????????????mKeyguardService.setOccluded(mKeyguardState.occluded);?? ????????????}?? ????????}?? ?? ????????@Override?? ????????public?void?onServiceDisconnected(ComponentName?name)?{?? ????????????if?(DEBUG)?Log.v(TAG,?"***?Keyguard?disconnected?(boo!)");?? ????????????mKeyguardService?=?null;?? ????????}?? ?? ????};?? ????...?? }??
當mKeyguardState.systemIsReady為true是,就會通過KeyguardServiceWrapper的實例mKeyguardService調用onSystemReady方法,在
KeyguardServiceWrapper的onSystemReady里調用了上面剛剛綁定成功的KeyguardService的onSystemReady方法
[java]?view plain
?copy ?? public?class?KeyguardServiceWrapper?implements?IKeyguardService?{?? ????...?? ????@Override??? ????public?void?onSystemReady()?{?? ????????try?{?? ????????????mService.onSystemReady();?? ????????}?catch?(RemoteException?e)?{?? ????????????Slog.w(TAG?,?"Remote?Exception",?e);?? ????????}?? ????}?? ????...?? }??
在KeyguardService的onSystemReady里調用了KeyguardViewMediator里的onSystemReady,在這里就不貼這個代碼了,直接看看KeyguardViewMediator.onSystemReady這個里面干啥了
2、KeyguardViewMediator.onSystemReady
[java]?view plain
?copy ?? public?class?KeyguardViewMediator?extends?SystemUI?{?? ????...?? ????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();?? ????}?? ????...?? }??
在這個方法里主要調用了doKeyguardLocked和注冊了KeyguardUpdateMonitorCallback
3、通過調用doKeyguardLocked顯示鎖屏界面
[java]?view plain
?copy ?? public?class?KeyguardViewMediator?extends?SystemUI?{?? ????...?? ????private?void?doKeyguardLocked(Bundle?options)?{?? ?????????? ????????if?(!mExternallyEnabled)?{?? ????????????if?(DEBUG)?Log.d(TAG,?"doKeyguard:?not?showing?because?externally?disabled");?? ?? ?????????????? ?????????????? ?????????????? ?????????????? ?????????????? ?????????????? ?????????????? ?????????????? ?????????????? ????????????return;?? ????????}?? ?? ?????????? ????????if?(mStatusBarKeyguardViewManager.isShowing())?{?? ????????????if?(DEBUG)?Log.d(TAG,?"doKeyguard:?not?showing?because?it?is?already?showing");?? ????????????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())?{?? ????????????if?(DEBUG)?Log.d(TAG,?"doKeyguard:?not?showing?because?device?isn't?provisioned"?? ????????????????????+?"?and?the?sim?is?not?locked?or?missing");?? ????????????return;?? ????????}?? ?? ????????if?(mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())?? ????????????????&&?!lockedOrMissing)?{?? ????????????if?(DEBUG)?Log.d(TAG,?"doKeyguard:?not?showing?because?lockscreen?is?off");?? ????????????return;?? ????????}?? ?? ????????if?(mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser()))?{?? ????????????if?(DEBUG)?Log.d(TAG,?"Not?showing?lock?screen?since?just?decrypted");?? ?????????????? ????????????setShowingLocked(false);?? ????????????hideLocked();?? ????????????mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();?? ????????????return;?? ????????}?? ?? ????????if?(DEBUG)?Log.d(TAG,?"doKeyguard:?showing?the?lock?screen");?? ????????showLocked(options);?? ????}?? ????...?? }??
這段代碼主要是在是否要顯示鎖屏之前做了5個判斷:1.如果啟用第三方鎖屏界面,不顯示原生界面;2.鎖屏界面已經顯示了話,重新更新下狀態;3.如果第一次開機引導界面setup wizard?還沒有運行,也先不顯示;4.屏幕沒有亮不顯示;5.當前正在解密界面不顯示。如果這幾個條件都不滿足,則調用showLocked顯示鎖屏界面。在
showLocked通過mHandler發送Message,在handleMessage里“case SHOW:”時調用handleShow
4、在handleShow里設置一些鎖屏狀態和顯示鎖屏界面
[java]?view plain
?copy ?? public?class?KeyguardViewMediator?extends?SystemUI?{?? ????...?? ????????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();?? ????}?? ????...?? }??
5、通過調用StatusBarKeyguardViewManager的show重置當前狀態顯示keyguard
[java]?view plain
?copy ?? public?class?StatusBarKeyguardViewManager?{?? ????...?? ????public?void?show(Bundle?options)?{?? ????????mShowing?=?true;?? ????????mStatusBarWindowManager.setKeyguardShowing(true);?? ????????mScrimController.abortKeyguardFadingOut();?? ????????reset();?? ????}?? ????...?? }??
在reset里調用本類的showBouncerOrKeyguard,在這個方法里通過KeyguardBouncer的實例mBouncer調用prepare(),在
prepare里調用了KeyguardHostView的showPrimarySecurityScreen
6、KeyguardSecurityContainer.showPrimarySecurityScreen
在KeyguardHostView的showPrimarySecurityScreen里調用KeyguardSecurityContainer的showPrimarySecurityScreen方法,如下
[java]?view plain
?copy ?? public?class?KeyguardSecurityContainer?extends?FrameLayout?implements?KeyguardSecurityView?{?? ????...?? ????void?showPrimarySecurityScreen(boolean?turningOff)?{?? ????????SecurityMode?securityMode?=?mSecurityModel.getSecurityMode();?? ????????if?(DEBUG)?Log.v(TAG,?"showPrimarySecurityScreen(turningOff="?+?turningOff?+?")");?? ????????showSecurityScreen(securityMode);?? ????}?? ????...?? }??
在這個方法里調用了showSecurityScreen,根據mSecurityModel.getSecurityMode()獲取的SecurityMode來顯示不同界面,SecurityMode定義如下
[java]?view plain
?copy ?? public?class?KeyguardSecurityModel?{?? ????public?enum?SecurityMode?{?? ????????Invalid,??? ????????None,??? ????????Pattern,??? ????????Password,??? ????????PIN,??? ????????SimPin,??? ????????SimPuk??? ????}?? ????...?? }??
showSecurityScreen方法如下:
[java]?view plain
?copy ?? public?class?KeyguardSecurityContainer?extends?FrameLayout?implements?KeyguardSecurityView?{?? ????...?? ????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. 在KeyguardServiceDelegate里綁定KeyguardService,并調用onSystemReady方法。
? ?2. KeyguardViewMediator里調用doKeyguardLocked來決定是否需要顯示鎖屏界面;如果顯示則調用StatusBarKeyguardViewManager的show,最后調用到KeyguardHostView的showPrimarySecurityScreen()。
? ?3. 在KeyguardSecurityContainer的showPrimarySecurityScreen利用mSecurityModel.getSecurityMode()獲取當前的securityMode,傳入showSecurityScreen來顯示不同鎖屏界面。
原文地址: http://blog.csdn.net/yin1031468524/article/details/56284449
總結
以上是生活随笔為你收集整理的Android 7.1.1 锁屏界面启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。