锁屏初始化入口KeyguardViewMediator
- 系统启动
SystemUI:当 Android 系统启动时,SystemUIApplication会解析配置,并创建一系列系统UI组件(即SystemUI的子类)的实例。KeyguardViewMediator就是其中之一。 - 框架回调
start():在创建了所有SystemUI服务实例后,SystemUIApplication会遍历并调用每个服务的start()方法。因此,KeyguardViewMediator的start()方法是由其父类SystemUI的启动机制调用的,这是一个标准的框架回调流程。 start()内部初始化 :在KeyguardViewMediator的start()方法内部,会执行一系列初始化操作,例如创建KeyguardDisplayManager实例,用于管理锁屏界面的显示。
csharp
//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
public void start() {
synchronized (this) {
//初始化
setupLocked();
}
}
锁屏页面显示流程
阶段一:系统启动 & 服务初始化
SystemServer启动 :系统启动时,SystemServer进程在startOtherServices()方法中启动各种核心服务,其中就包括调用WindowManagerService.systemReady()WindowManagerService转发 :WindowManagerService的systemReady()方法会继续调用PhoneWindowManager.systemReady()PhoneWindowManager中转 :PhoneWindowManager(作为WindowManagerPolicy的实现)的systemReady()方法,会进一步调用KeyguardServiceDelegate.onSystemReady()- 跨进程调用 :
KeyguardServiceDelegate是一个代理,它会通过KeyguardServiceWrapper,跨进程调用到KeyguardService(运行在 SystemUI 进程)的onSystemReady()方法 - 最终回调 :
KeyguardService的onSystemReady()方法内部,最终回调到了KeyguardViewMediator.onSystemReady()
scss
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public void systemReady() {
mSystemReady = true;
//WindowManagerPolicy mPolicy的实现类是PhoneWindowManager
mPolicy.systemReady();
mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
mTaskSnapshotController.systemReady();
...
}
}
}
//frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
public void systemReady() {
// In normal flow, systemReady is called before other system services are ready.
// So it is better not to bind keyguard here.
//代理类KeyguardServiceWrapper
mKeyguardDelegate.onSystemReady();
...
updateUiMode();
mDefaultDisplayRotation.updateOrientationListener();
synchronized (mLock) {
mSystemReady = true;
mHandler.post(new Runnable() {
@Override
public void run() {
updateSettings();
}
});
// If this happens, for whatever reason, systemReady came later than systemBooted.
// And keyguard should be already bound from systemBooted
if (mSystemBooted) {
mKeyguardDelegate.onBootCompleted();
}
}
...
}
//frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
public void onSystemReady() {
try {
//IKeyguardService mService
mService.onSystemReady();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
public void onSystemReady() {
...
//KeyguardViewMediator mKeyguardViewMediator
mKeyguardViewMediator.onSystemReady();
...
}
阶段二:视图创建与显示
这个阶段由 KeyguardViewMediator 发起,但视图的创建和显示工作被委托给了其他组件。
-
KeyguardViewMediator.doKeyguardLocked():此方法会进行一系列检查,例如锁屏功能是否启用 (config_enableKeyguard)、是否被其它策略禁用等。如果所有条件满足,它会调用showLocked()等方法 -
通知
StatusBar:KeyguardViewMediator通过内部回调机制,去显示锁屏。 -
StatusBar调用KeyguardViewController:StatusBar作为顶层的控制器,会调用KeyguardViewController接口的show(...)方法。- 关键点 :
KeyguardViewController是一个接口,其实现类是StatusBarKeyguardViewManager。但KeyguardViewMediator不再直接持有它,而是由StatusBar来管理这个实例。
- 关键点 :
-
KeyguardViewController构建视图 :StatusBarKeyguardViewManager的show()方法会负责显示完整的锁屏界面(包括NotificationPanelView、KeyguardBouncer等)。
scss
//frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
public void onSystemReady() {
mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
}
private void handleSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
//主要调用方法
doKeyguardLocked(null);
...
}
...
}
private void doKeyguardLocked(Bundle options) {
...
//如果已经显示直接返回
if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
resetStateLocked();
return;
}
...
//显示锁屏
showLocked(options);
}
private void showLocked(Bundle options) {
//发消息到消息队列
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);
}
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");
}
mHiding = false;
mKeyguardExitAnimationRunner = null;
mWakeAndUnlocking = false;
mPendingLock = false;
setShowingLocked(true);
//调用KeyguardViewController的实现类StatusBarKeyguardViewManager
mKeyguardViewControllerLazy.get().show(options);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
mUpdateMonitor.setKeyguardGoingAway(false);
mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
...
}
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
*/
@Override
public void show(Bundle options) {
mShowing = true;
//通知栏锁屏状态更新
mNotificationShadeWindowController.setKeyguardShowing(true);
mKeyguardStateController.notifyKeyguardState(mShowing,
mKeyguardStateController.isOccluded());
reset(true /* hideBouncerWhenShowing */);
...
}
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
// Hide quick settings.
mNotificationPanelViewController.resetViews(/* animate= */ true);
// Hide bouncer and quick-quick settings.
if (mOccluded && !mDozing) {
mStatusBar.hideKeyguard();
if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
hideBouncer(false /* destroyView */);
}
} else {
//
showBouncerOrKeyguard(hideBouncerWhenShowing);
}
...
}
}
阶段三:普通锁屏页面与安全锁屏页面交互
KeyguardBouncer处理验证 :如果用户设置了安全锁(PIN、图案、密码等),具体的验证逻辑由KeyguardBouncer组件处理。它负责显示相应的输入界面并校验用户输入。- 通知
KeyguardViewMediator:验证成功后,KeyguardBouncer会通过回调通知KeyguardViewMediator解锁成功(例如调用keyguardDone()等方法)。 KeyguardViewMediator处理善后 :KeyguardViewMediator执行解锁后的系统级操作,如播放声音、通知PowerManagerService等。- 隐藏锁屏视图 :最后,
KeyguardViewMediator会通知StatusBar,再由StatusBar通过KeyguardViewController去执行隐藏锁屏界面的操作。
scss
//frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
if (mBouncer.needsFullscreenBouncer() && !mDozing) {
//通知状态栏隐藏普通锁屏界面
mStatusBar.hideKeyguard();
//显示锁屏安全页面
mBouncer.show(true /* resetSecuritySelection */);
} else {
//通知状态栏显示普通锁屏界面
mStatusBar.showKeyguard();
if (hideBouncerWhenShowing) {
////隐藏锁屏安全页面
hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
mBouncer.prepare();
}
}
updateStates();
}