Android: Keyguard分析之一:开机流程篇
Keyguard 与 SystemUI运行在同一进程中,即com.android.systemui进程。这点可以从manifest.xml文件就可以看出:
# Keyguard Android.mk # SystemUI Android.mk
通过Android.mk可知:在编译过程中,keyguard被打包成静态Java库. Keygaurd实际是由SystemUI来管理的.
# Keyguard Android.mkinclude $(BUILD_STATIC_JAVA_LIBRARY)# SystemUI:LOCAL_STATIC_JAVA_LIBRARIES := \ com.mediatek.systemui.ext \ Keyguard \
开机时, keyguard视图的绘制流程
开机, Keyguard视图的形成过程:伴随着系统的启动,SystemServer将启动各种服务.对于Keyguard的服务而言.首先从startOtherServices()方法开始.
# SystemServer.java private void startOtherServices() { ... wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore); ... try { wm.systemReady(); } catch (Throwable e) { reportWtf("making Window Manager Service ready", e); }}
因为开机需要对Keyguard的视图进行绘制, 所以进入到了WindowManagerService服务中(对系统中的所有窗口进行管理是窗口管理服务WindowManagerService的职责).在WindowManagerService.java中直接调用了WindowManagerPolicy.java的systemReady()方法,而具体方法的实现在PhoneWindowManager.java中。
# PhoneWindowManager.javapublic void systemReady() { mKeyguardDelegate = new KeyguardServiceDelegate(mContext); mKeyguardDelegate.onSystemReady(); //分派到KeyguardDelegate进行处理,开机时不做任何处理. ... synchronized (mLock) { ... bindKeyguardNow = mDeferBindKeyguard; if (bindKeyguardNow) { // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. mDeferBindKeyguard = false; } } if (bindKeyguardNow) {//如果已经绑定KeyguardService,进行处理. mKeyguardDelegate.bindService(mContext); mKeyguardDelegate.onBootCompleted(); } ... }
在进入KeyguardServiceDelegate.java, 将绑定keyguardService服务.
private final ServiceConnection mKeyguardConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { ... mKeyguardService.onSystemReady(); ... } ... };
可以发现 mKeyguardDelegate.onSystemReady()进入到了KeyguardServiceWrapper,并将任务分派到KeyguardService,启动Keyguard服务.
# KeyguardServiceWrapper.javapublic class KeyguardServiceWrapper implements IKeyguardService {}# KeyguardService.java private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() { public void onSystemReady() { checkPermission(); //权限的检查. mKeyguardViewMediator.onSystemReady(); } }
可以看出,其实这两个类就是跨进程通信.通过IKeyguardService这个接口来进行framework与Systemui之间的跨进程通信.此时,流程就进入到了SystemUI.
进入SystemUI这个应用后, 将进入Keyguard的一个重要的类KeyguardViewMediator.先看看调用的方法.该方法主要是进行广播:标志这系统在启动后已经准备好了.接着,doKeyguardLocked()方法收到了null参数. 可以看到这个方法主要是针对不同的keyguard模式进行判别.
# KeyguardViewMediator.java //Let us know that the system is ready after startup. public void onSystemReady() { mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); synchronized (this) { ... mSystemReady = true; doKeyguardLocked(null); //锁屏路径 mUpdateMonitor.registerCallback(mUpdateCallback); mPowerOffAlarmManager.onSystemReady(); } mIsPerUserLock = StorageManager.isFileEncryptedNativeOrEmulated(); // Most services aren't available until the system reaches the ready state, so we // send it here when the device first boots. maybeSendUserPresentBroadcast(); } private void doKeyguardLocked(Bundle options) { // if another app is disabling us, don't show if (!mExternallyEnabled) {//外置apk的keyguard等 return; } // if the keyguard is already showing, don't bother if (mStatusBarKeyguardViewManager.isShowing()) { resetStateLocked(); return; } ... //doKeyguard: not showing because device isn't provisioned //and the sim is not locked or missing if (!lockedOrMissing && shouldWaitForProvisioning() && !antiTheftLocked) { return; } //doKeyguard: not showing because lockscreen is off if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing && !antiTheftLocked) { return; } //解密后的状态也不显示keyguard. if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser()) && KeyguardUtils.isSystemEncrypted()) { setShowingLocked(false); hideLocked(); mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt(); return; } ... showLocked(options); } private void showLocked(Bundle options) { setReadyToShow(true) ;设置参数. updateActivityLockScreenState();//更新锁屏状态,使用进程间通信技术 // ensure we stay awake until we are finished displaying the keyguard mShowKeyguardWakeLock.acquire(); //获取唤醒锁.不受电源影响,不让cpu进入休眠状态. Message msg = mHandler.obtainMessage(SHOW, options); mHandler.sendMessage(msg); //使用handler子线程来处理显示 } private void handleShow(Bundle options) { final int currentUser = KeyguardUpdateMonitor.getCurrentUser(); if (mLockPatternUtils.isSecure(currentUser)) { mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser); } synchronized (KeyguardViewMediator.this) { setShowingLocked(true); mStatusBarKeyguardViewManager.show(options);//keyguard的显示. mHiding = false; mWakeAndUnlocking = false; resetKeyguardDonePendingLocked(); ///M: reset mReadyToShow setReadyToShow(false) ; mHideAnimationRun = false; updateActivityLockScreenState(); adjustStatusBarLocked(); userActivity(); mShowKeyguardWakeLock.release(); } if (mKeyguardDisplayManager != null) { mKeyguardDisplayManager.show(); } }
最后跳转到Keyguard中去显示.通过开机时的log,亦发现开机显示keyguard的一瞬间,打印出了"show".
# KeyguardDisplayManager.java public void show() { if (!mShowing) { ... mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); updateDisplays(true); } mShowing = true; }
现在显示keyguard的流程就结束了.当然这个流程显示的是 ++滑动进入锁屏界面前的那个界面++.
再来看看mStatusBarKeyguardViewManager.show(options).
# StatusBarKeyguardViewManager.java public void show(Bundle options) { mShowing = true; mStatusBarWindowManager.setKeyguardShowing(true); mScrimController.abortKeyguardFadingOut(); reset(); }
reset()这个方法判断显示状态,再进行处理
# StatusBarKeyguardViewManager.java public void reset() { ... if (mShowing) { if (mOccluded) {//是否被其他窗口中断 mPhoneStatusBar.hideKeyguard(); mPhoneStatusBar.stopWaitingForKeyguardExit(); mBouncer.hide(false /* destroyView */); } else { showBouncerOrKeyguard();//滑动锁或Keyguard锁. } KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); updateStates(); } } // showBouncerOrKeyguard()方法使用KeyguardBouncer.java的needsFullscreenBo // uncer()方法判断显示常规锁屏还是Bouncer安全锁屏(比如图案锁屏、密码锁屏 // PIN码锁屏等); protected void showBouncerOrKeyguard() {//判断锁使用的锁的类型. ... if (mBouncer.needsFullscreenBouncer()) { // The keyguard might be showing (already). So we need to hide it. mPhoneStatusBar.hideKeyguard(); mBouncer.show(true /* resetSecuritySelection */); } else { mPhoneStatusBar.showKeyguard(); mBouncer.hide(false /* destroyView */); mBouncer.prepare(); } }
看看mBouncer是哪几种keyguard.这类被称为: Bouncer安全锁屏, 包括: PIM码 , PUK码等锁屏方式的锁屏界面,这类所直接在systemui中处理了.通过KeyguardBouncer.java来开始控制show()和hide();
# KeyguardBouncer.java public boolean needsFullscreenBouncer() { ... return mode == SecurityMode.SimPinPukMe1 || mode == SecurityMode.SimPinPukMe2 || mode == SecurityMode.SimPinPukMe3 || mode == SecurityMode.SimPinPukMe4 || mode == SecurityMode.AntiTheft || mode == SecurityMode.AlarmBoot; } # KeyguardSecuritymodel.java public enum SecurityMode { Invalid, // NULL state None, // No security enabled Pattern, // Unlock by drawing a pattern. Password, // Unlock by entering an alphanumeric password PIN, // Strictly numeric password // SimPin, // Unlock by entering a sim pin. // SimPuk, // Unlock by entering a sim puk SimPinPukMe1, // Unlock by entering a sim pin/puk/me for sim or gemini sim1. SimPinPukMe2, // Unlock by entering a sim pin/puk/me for sim or gemini sim2. SimPinPukMe3, // Unlock by entering a sim pin/puk/me for sim or gemini sim3. SimPinPukMe4, // Unlock by entering a sim pin/puk/me for sim or gemini sim4. AlarmBoot, // add for power-off alarm. Biometric, // Unlock with a biometric key (e.g. voice unlock) Voice, // Unlock with voice password AntiTheft // Antitheft feature }
则其他为一般解锁, 其将进入到Keyguard中去进行处理. 称为:notification keyguard, 包括 品pattern, password,PIN,None(滑动解锁).这中解锁方式有个特点:在进入解锁界面前,会出现我们之前分析的界面, ++滑动进入锁屏界面前的那个界面++. 这种keyguard的视图的父视图为KeyguardSecurityContainer.
接着,还是进入KeyguardBouncer进行keyguard视图的绘制.
# KeyguardBouncer.java public void prepare() { ... if (wasInitialized) { mKeyguardView.showPrimarySecurityScreen(); } ... }
之后直接跳到了KeyguardHostView.java,并传入了false参数, 进入到KeyguardSecurityContainer.java.
# KeyguardSecurityContainer.java void showPrimarySecurityScreen(boolean turningOff) { ... showSecurityScreen(securityMode); }
最后根据不同的keyguard的模式来进行界面的重绘
# KeyguardSecurityContainer.javaprivate void showSecurityScreen(SecurityMode securityMode) { ... mCurrentSecuritySelection) ; KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection); Log.d(TAG, "showSecurityScreen() - get newview for" + securityMode) ; KeyguardSecurityView newView = getSecurityView(securityMode); ... }
通过该方法通过传入的mode来绘制出相应的keyguard视图.
# KeyguardSecurityContainer.java private KeyguardSecurityView getSecurityView(SecurityMode securityMode) { ... int layoutId = getLayoutIdFor(securityMode);//通过mode选择对应的keyguard的view视图. if (view == null && layoutId != 0) { final LayoutInflater inflater = LayoutInflater.from(mContext); View v = inflater.inflate(layoutId, mSecurityViewFlipper, false); view = (KeyguardSecurityView) v; ... mSecurityViewFlipper.addView(v); updateSecurityView(v); // view = (KeyguardSecurityView)v; } ... return view; }
在完成一系列的绘制视图工作后.
1. 从SystemServer开始, 通过WindowManagerPolicy进入到KeyguardServiceDelegate.
2. KeyguardServiceDelegate绑定KeyService服务,此时进入到SystemUI.并调用KeyguardViewMediator决定是否显示视图.
3. 若显示视图,将StatusBarKeyguardViewManager来重置,并进入到KeyguardBouncer.
4. 最后进入到KeyguardSecurityContainer,根据不同的模式绘制不同的keyguard视图.
---
> KeyguardServiceDelegate.java 继承了接口IKeyguardService; 同时KeyguardService完成了IKeyguardService的远程实现. 即这两个类通过底层aidl进行远程通信. 进入系统可以控制Keyguard服务的启动.
> KeyguardServiceDelegate.java 是一个局部类,保存keyguard在崩溃之前的状态,用来恢复. 同时它也可以运行时选择本地或远程的keyguard实例.
> KeyguardViewMediator.java 作为一个中介类, 连接Keyguard与Systemui.其职能包括查询keyguard的状态, Keyguard在开关键的事件的动作,如显示或重置等.
> KeyguardSecurityContainer.java 这个类主要用于装载Pattern, password, pin等解锁视图的容器.
> KeyguardUpdateMonitor.java 类似于一个监视器, 用于监听keyguard的更新变化.
> StatusBarKeyguardViewManger.java 在status bar中, 管理创建, 显示, 隐藏, 重置 状态栏中的 Keyguard.
---
现在根据上述流程, 打印log, 来验证流程的正确性.
```
01-03 21:49:03.050 698 698 D @ying : SystemServer.startOtherservices.wm.systemReady begin
01-03 21:49:03.050 698 698 D @ying : PhoneWindowManager.systemReady begin
01-03 21:49:03.051 698 698 D @ying : PhoneWindowManager.systemReady end
01-03 21:49:03.054 698 698 D @ying : SystemServer.startOtherservices.wm.systemReady end
01-03 21:49:06.938 698 725 D @ying : KeyguardServiceDelegate.mKeyguardConnection begin
01-03 21:49:06.942 698 725 D @ying : KeyguardServiceDelegate.mKeyguardConnection:mKeyguardState.systemIsReady begin
01-03 21:49:06.942 698 725 D @ying : KeyguardServiceWrapper.onSystemReady begin
01-03 21:49:06.942 698 725 D @ying : KeyguardServiceWrapper.onSystemReady end
01-03 21:49:06.942 698 725 D @ying : KeyguardServiceDelegate.mKeyguardConnection:mKeyguardState.systemIsReady begin
01-03 21:49:06.943 698 725 D @ying : KeyguardServiceDelegate.mKeyguardConnection begin
01-03 21:49:06.945 935 1204 D @ying : KeyguardService.onSystemReady begin
01-03 21:49:06.945 935 1204 D @ying : KeyguardViewMediator.onSystemReady begin
01-03 21:49:06.958 935 1204 D @ying : KeyguardViewMediator.doKeyguardLocked begin
01-03 21:49:06.958 935 1204 D @ying : KeyguardViewMediator.showLocked begin
01-03 21:49:06.965 935 1204 D @ying : KeyguardViewMediator.showLocked end
01-03 21:49:06.966 935 1204 D @ying : KeyguardViewMediator.doKeyguardLocked end
01-03 21:49:06.966 935 1204 D @ying : KeyguardViewMediator.onSystemReady begin
01-03 21:49:06.976 935 1204 D @ying : KeyguardService.onSystemReady end
01-03 21:49:07.104 935 935 D @ying : KeyguardViewMeditor.handleShow begin
01-03 21:49:07.104 935 935 D @ying : StatusBarKeyguardViewManager.show begin
01-03 21:49:07.105 935 935 D @ying : StatusBarKeyguardViewManager.reset begin
01-03 21:49:07.105 935 935 D @ying : StatusBarKeyguardViewManager.reset:mOccluded-false begin
01-03 21:49:07.105 935 935 D @ying : StatusBarKeyguardViewManager.showBouncerOrKeyguard begin
01-03 21:49:07.118 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen begin
01-03 21:49:07.120 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen:showSecurityScreen
01-03 21:49:07.121 935 935 D @ying : KeyguardSecurityContainer.showSecurityScreen begin
01-03 21:49:07.122 935 935 D @ying : KeyguardSecurityContainer.showSecurityScreen newView begin
01-03 21:49:07.202 935 935 D @ying : KeyguardSecurityContainer.showSecurityScreen newView end
01-03 21:49:07.225 935 935 D @ying : KeyguardSecurityContainer.showSecurityScreen end
01-03 21:49:07.225 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen end
01-03 21:49:07.336 935 935 D @ying : needsFullscreenBouncer() is false,show "Notification Keyguard" view.
01-03 21:49:07.397 935 935 D @ying : KeyguardBouncer.prepare begin
01-03 21:49:07.397 935 935 D @ying : KeyguardBouncer.prepare:wasInitialized
01-03 21:49:07.398 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen begin
01-03 21:49:07.401 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen:showSecurityScreen
01-03 21:49:07.401 935 935 D @ying : KeyguardSecurityContainer.showSecurityScreen begin
01-03 21:49:07.401 935 935 D @ying : KeyguardSecurityContainer.showPrimarySecurityScreen end
01-03 21:49:07.422 935 935 D @ying : KeyguardBouncer.prepare end
01-03 21:49:07.422 935 935 D @ying : StatusBarKeyguardViewManager.showBouncerOrKeyguard end
01-03 21:49:07.422 935 935 D @ying : StatusBarKeyguardViewManager.reset:mOccluded-false end
01-03 21:49:07.442 935 935 D @ying : StatusBarKeyguardViewManager.reset end
01-03 21:49:07.443 935 935 D @ying : StatusBarKeyguardViewManager.show end
01-03 21:49:07.443 935 935 D @ying : KeyguardViewMeditor.handleShow end
01-03 21:49:07.451 935 935 D @ying : KeyguardViewMediator.handleShow:mKeyguardDisplayManager begin
01-03 21:49:07.451 935 935 D @ying : KeyguardViewMediator.handleShow:mKeyguardDisplayManager end
```
从 Log 日志再来梳理一遍开机时, Keyguard的流程走向.
>1. 开机, 完成开机动画后, SystemServer这个系统服务线程由底层开启, 该系统服务将开启一系列的服务, 其中Keyguard的流程会流到WindowManagerPolicy进行处理.
>2. WindowManagerPolicy的实现类是PhoneWindowManager. 其将 keyguard 事件分发到 KeyguardServiceDelegate进行处理.
>3. KeyguardServiceDelegate 开启了Keyguard服务, IkeyguardService由KeyguardServiceWrapper包装类继承,由KeyguardService远程实现. 实现底层与Systemui的通信,保证两者之间数据共享.
>4. keyguard事件传递到了SystemUI, 并由KeyguardViewMediator进行事件的分派. 如部分视图由SystemUI显示,即如StatusBarKeyguardViewManager来处理. 部分视图将传递到Keyguard,由Keyguard来绘制, 如 KeyguardSecurityContainer来处理.
更多相关文章
- android 开发 View _1_ View的子类们 和 视图坐标系图
- android 左右滑动+索引图标实现方法与代码
- Android(安卓)应用获取通知栏权限是否开启,并跳转设置界面
- Android发送邮件的方法实例详解
- Android(安卓)多个listview监听item的点击事件
- android 模拟back键
- 32、详解Android(安卓)shape的使用方法
- Android(安卓)service启动流程分析.
- 去掉所有Activity界面的标题栏、强制横屏坚屏