学习笔记:参考资源 https://blog.csdn.net/qq_15347925/article/details/116722133
一、流程概述
1、SystemUI启动完成后,进入的第一个界面为锁屏界面。
2、锁屏keyguard属于SystemUI。
3、锁屏开机大致分为两部分,第一部分是从WindowManagerService开始,处理锁屏显示等流程。第二部分是KeyguardViewMediator的启动;
Keyguard时序图.png
二、详细介绍
1 WindowManagerService部分:
WindowManagerService在SystemService中的startOtherServices()方法里启动。
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new SprdPhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();
SystemServer在启动SystemUI()的方法上,最后调用WindowManagerService的onSystemUiStarted方法。
private static void startSystemUi(Context context, WindowManagerService windowManager) {
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
Intent intent = new Intent();
intent.setComponent(pm.getSystemUiServiceComponent());
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
继续跟进,会发现WindowManagerService的onSystemUiStarted方法,实际调用的是PhoneWindowManager中的onSystemUiStarted();(通过接口进行回调)
@Override
public void onSystemUiStarted() {
bindKeyguard();
}
在PhoneWindowManager中会调用bindKeyguard,KeyguardServiceDelegate作为KeyguardService的委派。
private void bindKeyguard() {
synchronized (mLock) {
if (mKeyguardBound) {
return;
}
mKeyguardBound = true;
}
mKeyguardDelegate.bindService(mContext);
}
在KeyguardServiceDelegate的bindService方法中绑定KeyguardService。
public void bindService(Context context) {
Intent intent = new Intent();
final Resources resources = context.getApplicationContext().getResources();
//从配置文件中获取KeyguardService
final ComponentName keyguardComponent = ComponentName.unflattenFromString(
resources.getString(com.android.internal.R.string.config_keyguardComponent));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
intent.setComponent(keyguardComponent);
//绑定KeyguardService
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
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;
}
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
}
在ServiceConnection的连接成功回调中,创建KeyguardService包装类KeyguardServiceWrapper。包装类除了KeyguardService,还有KeyguardStateMonitor状态监视器。实际调用还是通过KeyguardService。
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
// KeyguardServiceWrapper包装类调用KeyguardService的Binder实例
mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service), mCallback);
if (mKeyguardState.systemIsReady) {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
// There has been a user switch earlier
mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
}
// 调用KeyguardService的IPC接口
..
..
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
mKeyguardState.reset();
..
}
}
在绑定以后,PhoneWindowManager可以调用代理类KeyguardServiceDelegate间接调用KeyguardService的binder接口进行各种锁屏相关状态回调。
2 KeyguardViewMediato 部分
初次开机Keyguard showLock流程:
系统启动完成-->PhoneWindowManager.systemReady()-->mKeyguardDelegate.onSystemReady()
-->mKeyguardService.onSystemReady()-->KeyguardService.onSystemReady()
在KeyguardService绑定成功后调用了onSystemReady方法。onSystemReady最终的处理流程是在KeyguardViewMediator的onSystemReady方法
frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@Override // Binder interface
public void onSystemReady() {
Trace.beginSection("KeyguardService.mBinder#onSystemReady");
checkPermission();
mKeyguardViewMediator.onSystemReady();
Trace.endSection();
}
KeyguardViewMediator中的onSystemReady方法发送了一条handler消息。经过消息传递会由handleSystemReady方法处理。handleSystemReady方法的关键调用是doKeyguardLocked。
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); // handleSystemReady方法的关键调用是doKeyguardLocked。
mUpdateMonitor.registerCallback(mUpdateCallback);
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
}
/**
* Enable the keyguard if the settings are appropriate.
*/
private void doKeyguardLocked(Bundle options) {
...
//1. 判断其他应用禁止锁屏呈现。
//2. 判断是否需要重置状态。
//3. 判断Settings中没有启用锁屏 。
//4. 判断是否设置了密码等。
...
//显示锁屏
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
showLocked(options);
}
/**
* showLocked显示锁屏方法主要处理:请求CPU不休眠,发送显示锁屏消息。
*/
private void showLocked(Bundle options) {
Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");
if (DEBUG) Log.d(TAG, "showLocked");
// ensure we stay awake until we are finished displaying the keyguard
// 获取PARTIAL_WAKE_LOCK,不受电源键影响,不让CPU进入休眠状态
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);
Trace.endSection();
}
/**
* handleShow() 处理锁屏消息的方法
*/
private void handleShow(Bundle options) {
..
synchronized (KeyguardViewMediator.this) {
..
setShowingLocked(true);
// 显示keyguard
mStatusBarKeyguardViewManager.show(options);
..
// 释放mShowKeyguardWakeLock
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
Trace.endSection();
}
在handleShow中调用StatusBarKeyguardViewManager方法,锁屏处理由KeyguardViewMediator转移到StatusBarKeyguardViewManager。
3 其他各重要部分
3.1 StatusBarKeyguardViewManager
StatusBarKeyguardViewManager中show方法设置keyguard是否显示,通知statusbar显示锁屏,重置view的状态,进行锁屏。
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
//重置状态
reset(true /* hideBouncerWhenShowing */);
StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
}
StatusBarKeyguardViewManager中reset方法,主要调用showBouncerOrKeyguard方法。判断显示默认锁屏界面还是显示密码锁屏。默认锁屏界面由StatusBar管理,而密码解锁则调用KeyguardBouncer类。
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
//是否需要显示密码锁屏界面
if (mBouncer.needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
//隐藏锁屏,显示密码解锁界面
mStatusBar.hideKeyguard();
mBouncer.show(true /* resetSecuritySelection */);
} else {
mStatusBar.showKeyguard();
if (hideBouncerWhenShowing) {
hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
mBouncer.prepare();
}
}
updateStates();
}
3.2 KeyguardBouncer
在StatusBarKeyguardViewManager类中,StatusBar类则管理默认锁屏界面,KeyguardBouncer类控制密码解锁界面的,KeyguardBouncer会进行锁屏view的填充,KeyguardHostView是自定义容器,内部锁屏相关的处理在KeyguardSecurityContainer中。
private void showPrimarySecurityScreen() {
mKeyguardView.showPrimarySecurityScreen();
}
继续往下跟进,会发现最终会调用到KeyguardSecurityContainer类中,在showSecurityScreen方法中会根据锁屏的类型获得锁屏的view,并添加到KeyguardSecurityViewFlipper 。
private void showSecurityScreen(SecurityMode securityMode) {
if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
if (securityMode == mCurrentSecuritySelection) return;
KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
KeyguardSecurityView newView = getSecurityView(securityMode);
// Emulate Activity life cycle
if (oldView != null) {
oldView.onPause();
oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
}
if (securityMode != SecurityMode.None) {
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
newView.setKeyguardCallback(mCallback);
}
// Find and show this child.
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());
}
private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
KeyguardSecurityView view = null;
final int children = mSecurityViewFlipper.getChildCount();
for (int child = 0; child < children; child++) {
if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
break;
}
}
int layoutId = getLayoutIdFor(securityMode);
if (view == null && layoutId != 0) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);
mSecurityViewFlipper.addView(v);
updateSecurityView(v);
view = (KeyguardSecurityView)v;
}
return view;
}
3.3 StatusBar
StatusBar也是继承SystemUI,启动流程和SystemUI一致。并在start的时候添加创建StatusBar相关的view。
public void start() {
// 省略部分代码...
// 创建整个SystemUI视图并添加到WindowManager中
createAndAddWindows(result);
// 省略部分代码...
}
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
// 创建整个SystemUI视图
makeStatusBarView(result);
// 把视图添加到Window中
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
}
makeStatusBarView()负责创建整个SystemUI视图,其中包括状态栏。
代码路径: packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
// ...
// 1. 实例化整个SystemUI视图,包括状态栏,通知面版, 锁屏
mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
}
网友评论