Android 7.1.1 锁屏界面启动流程。前几天遇到一个低概率复现锁屏界面不显示,只显示状态栏的问题,跟了下锁屏界面启动显示的流程,在这分享下,也方便以后自己查看。前面简单介绍了下 Zygote 启动流程,Zygote 进程启动后会首先创建一个 SystemServer 进程,SystemServer 进程在调用 startOtherServices 同时也会调用 WindowManagerService 的 systemReady() 方法
- //frameworks/base/services/java/com/android/server/SystemServer.java 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()
- //frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java //final WindowManagerPolicy mPolicy = new PhoneWindowManager(); public void systemReady() { mPolicy.systemReady(); }
在 PhoneWindowManager 的 systemReady() 会根据一个 Boolean 值 bindKeyguardNow 来决定是否绑定 keyguard service
- //frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java /** {@inheritDoc} */ @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) { // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. mDeferBindKeyguard = false; } } if (bindKeyguardNow) { mKeyguardDelegate.bindService(mContext); mKeyguardDelegate.onBootCompleted(); } mSystemGestures.systemReady(); }
看到这里,可能会想到如果 bindKeyguardNow 为 false 就会不绑定,后面通过继续跟踪发现在 PhoneWindowManager 的 systemBooted() 里也会去绑定 keyguard service,如果在 systemBooted 里绑定了就不在 systemReady 里再去绑定,自己测试的时候是在 systemBooted 绑定的
- //frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java /** {@inheritDoc} */ @Override public void systemBooted() { boolean bindKeyguardNow = false; synchronized (mLock) { // Time to bind Keyguard; take care to only bind it once, either here if ready or // in systemReady if not. if (mKeyguardDelegate != null) { bindKeyguardNow = true; } else { // Because mKeyguardDelegate is null, we know that the synchronized block in // systemReady didn't run yet and setting this will actually have an effect. 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 的
- //frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.javapublic 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) { // TODO: Fix synchronisation model in this class. The other state in this class // is at least self-healing but a race condition here can lead to the scrim being // stuck on keyguard-less devices. mKeyguardState.deviceHasKeyguard = false; hideScrim(); } } else { if (DEBUG) Log.v(TAG, "*** Keyguard started"); } } ...}
在 bindService 中调用了 bindServiceAsUser 绑定指定 intent 的 service,config_keyguardComponent 的定义如下
- //frameworks/base/core/res/res/values/config.xml com.android.systemui/com.android.systemui.keyguard.KeyguardService
当绑定成功后会调用 mKeyguardConnection 里的 onServiceConnected 方法
来源: http://www.92to.com/bangong/2017/02-22/17392393.html