本文将以开机启动,初次展示PIN码解锁界面为主线,介绍KeyguardService的组织结构并分析密码解锁界面的呈现流程。
一.开机启动到PhoneWindowManager
开机启动init->zygote->systemserver进程
systemserver入口是main(),实例化systemserver对象并调用其run()方法。
在run()方法中,我们此次重点关注startOtherServices();
在startOtherServices()启动了WindowManagerService,
截取部分代码如下:
PhoneWindowManager.WindowManagerService:
private void startOtherServices() {
WindowManagerService wm = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);//启动服务
ServiceManager.addService(Context.WINDOW_SERVICE, wm);//注册到ServiceManager,供其他进程调用
......
wm.systemReady();
}
WindowManagerService.systemReady():
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
final WindowManagerPolicy mPolicy = new PhoneWindowManager();//生成PhoneWindowManager实例
public void systemReady() {
mPolicy.systemReady();//调用PhoneWindowManager.systemReady()
}
PhoneWindowManager.systemReady():
public void systemReady() {
mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
mKeyguardDelegate.onSystemReady();//实例锁屏代理类并调用其onSystemReady()
二.KeyguardService的组织结构
这里先放一张整体的流程图,方便大家查看分析:
KeyguardServiceDelegate.onSystemReady():
protected KeyguardServiceWrapper mKeyguardService;//锁屏服务包装类
public void onSystemReady() {
if (mKeyguardService != null) {
mKeyguardService.onSystemReady();
} else {
mKeyguardState.systemIsReady = true;
}
}
KeyguardServiceWrapper.onSystemReady():
private IKeyguardService mService;
public KeyguardServiceWrapper(Context context, IKeyguardService service) {
mService = service;//IKeyguardService在KeyguardServiceWrapper的构造函数中赋值
mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
public void onSystemReady() {
try {
mService.onSystemReady();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
可以看到KeyguardServiceWrapper对IKeyguardService进行了封装,其方法实现主要是对
IKeyguardService的调用。而IKeyguardService在在KeyguardServiceWrapper的构造函数中赋值。
KeyguardServiceWrapper在哪被实例化的呢?
后头看一下KeyguardServiceDelegate初始化的过程:
/**
* 使用bindService的方式来绑定服务。利用bindService的方式:
* 调用者与服务绑定在一起,调用者退出,服务即终止。
* ps => bind方式绑定服务,服务的执行顺序为:
* onCreate()->onBind()->onUnbind()->onDestroy()
*/
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));
//config_keyguardComponent->com.android.systemui/com.android.systemui.keyguard.KeyguardService
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
intent.setComponent(keyguardComponent);
//这里将KeyguardServiceDelegate与KeyguardService绑定到了一起。
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, mScrimHandler, 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;
hideScrim();
}
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
}
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
//通过onServiceConnected()拿到KeyguardService的Binder代理对象,并创建KeyguardService包装类
//实例化KeyguardServiceWrapper
mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service));
......
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
}
};
可以看到KeyguardServiceDelegate去绑定KeyguardService,KeyguardServiceDelegate就相当于一个客户端,而
KeyguardService即为服务端。
看一下KeyguardService:
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
private KeyguardViewMediator mKeyguardViewMediator;
@Override
public void onCreate() {
((SystemUIApplication) getApplication()).startServicesIfNeeded();
mKeyguardViewMediator =
((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;//此返回值将返回到KeyguardServiceDelegate的onServiceConnected(),通过这个Binder对象,客户端与服务端才能连接起来
}
//mBinder实例化,重写相关接口方法
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
@Override // Binder interface
public void onSystemReady() {
checkPermission();
mKeyguardViewMediator.onSystemReady();//实际KeyguardService调用KeyguardViewMediator的对应方法
}
......
}
}
KeyguardViewMediator.onSystemReady()
public void onSystemReady() {
synchronized (this) {
......
doKeyguardLocked(null);//锁屏调起的真正入口,进行锁屏预处理工作
......
}
}
三.KeyguardBouncer呈现流程
上文调用如下:
PhoneWindowManager.systemReady()->KeyguardServiceDelegate.onSystemReady()
->KeyguardServiceWrapper.onSystemReady()->KeyguardService.onSystemReady()->
KeyguardViewMediator.onSystemReady().
KeyguardViewMediator.doKeyguardLocked():
private void doKeyguardLocked(Bundle options) {
//如果其他应用阻止我们显示,那么就不显示。。例如:接打电话
if (!mExternallyEnabled || PowerOffAlarmManager.isAlarmBoot()) {
return;
}
//如果锁屏正在显示,那我们就不去显示
if (mStatusBarKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
resetStateLocked();
if (DEBUG) {
Log.d(TAG, "doKeyguard: not showing because it is already showing");
}
return;
}
......
//经过上述判断后,再去显示锁屏
showLocked(options);
}
KeyguardViewMediator.showLocked()
private void showLocked(Bundle options) {
......
//获取锁屏锁,不让cpu进入休眠,以完整的展示锁屏
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);//发送SHOW消息
}
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW:
handleShow((Bundle) msg.obj);
break;
KeyguardViewMediator.handleShow()
private void handleShow(Bundle options) {
mStatusBarKeyguardViewManager =
SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
synchronized (KeyguardViewMediator.this) {
......
mStatusBarKeyguardViewManager.show(options);//主要是调用了这里
......
StatusBarKeyguardViewManager.show():
public void show(Bundle options) {
......
reset();
}
StatusBarKeyguardViewManager.reset():
public void reset() {
if (mShowing) {
if (mOccluded) {//是否有遮挡物,如果有就隐藏锁屏,没有则判断显示锁屏还是密码解锁界面
mPhoneStatusBar.hideKeyguard();
mPhoneStatusBar.stopWaitingForKeyguardExit();
mBouncer.hide(false /* destroyView */);
} else {
showBouncerOrKeyguard();//判断显示锁屏还是密码解锁界面
}
KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
updateStates();
}
}
StatusBarKeyguardViewManager.showBouncerOrKeyguard():
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();
}
}
Bouncer.needsFullscreenBouncer():
public boolean needsFullscreenBouncer() {
ensureView();
SecurityMode mode = mSecurityModel.getSecurityMode();//获得当前是哪一种安全模式
return mode == SecurityMode.SimPinPukMe1
|| mode == SecurityMode.SimPinPukMe2
|| mode == SecurityMode.SimPinPukMe3
|| mode == SecurityMode.SimPinPukMe4
|| mode == SecurityMode.AntiTheft
|| mode == SecurityMode.AlarmBoot;
}
KeyguardSecurityModel.getSecurityMode():
public SecurityMode getSecurityMode() {
KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
SecurityMode mode = SecurityMode.None;
if (PowerOffAlarmManager.isAlarmBoot()) { /// M: add for power-off alarm
mode = SecurityMode.AlarmBoot;
} else {
//检查当前sim卡的Pin/Puk/Me是否均已解锁
for (int i = 0; i < KeyguardUtils.getNumOfPhone(); i++) {
if (isPinPukOrMeRequiredOfPhoneId(i)) {//判断此卡是否需要进行密码解锁
if (0 == i) {
mode = SecurityMode.SimPinPukMe1;
} else if (1 == i) {
mode = SecurityMode.SimPinPukMe2;
} else if (2 == i) {
mode = SecurityMode.SimPinPukMe3;
} else if (3 == i) {
mode = SecurityMode.SimPinPukMe4;
}
break;
}
}
}
//是否需要显示防盗保护
if (AntiTheftManager.isAntiTheftPriorToSecMode(mode)) {
Log.d("KeyguardSecurityModel", "should show AntiTheft!") ;
mode = SecurityMode.AntiTheft;
}
//如果当前安全模式不是sim卡的Pin/Puk/Me也不是防盗保护,则查看是PIN码,密码,还是手势
if (mode == SecurityMode.None) {
final int security = mLockPatternUtils.getActivePasswordQuality(
KeyguardUpdateMonitor.getCurrentUser());
switch (security) {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
return SecurityMode.PIN;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
return SecurityMode.Password;
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
return SecurityMode.Pattern;
case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
return SecurityMode.None;
default:
throw new IllegalStateException("Unknown security quality:" + security);
}
}
Log.d(TAG, "getSecurityMode() - mode = " + mode);
return mode;
}
本文以sim卡1的Pin码解锁为例,则getSecurityMode返回SecurityMode.SimPinPukMe1。至needsFullscreenBouncer(),
再至showBouncerOrKeyguard(),此时mBouncer.needsFullscreenBouncer()条件为真,隐藏锁屏,显示bouncer.
mBouncer.show(true /* resetSecuritySelection */);//重置安全选择
public void show(boolean resetSecuritySelection) {
......
show(resetSecuritySelection, false) ;
}
public void show(boolean resetSecuritySelection, boolean authenticated) {
......
if (resetSecuritySelection) {//此时resetSecuritySelection为true
// showPrimarySecurityScreen() updates the current security method. This is needed in
// case we are already showing and the current security method changed.
mKeyguardView.showPrimarySecurityScreen();
}
......
}
public void showPrimarySecurityScreen() {
mSecurityContainer.showPrimarySecurityScreen(false);
}
KeyguardSecurityContainer.showPrimarySecurityScreen();
void showPrimarySecurityScreen(boolean turningOff) {
//获取当前安全模式,上文分析过
SecurityMode securityMode = mSecurityModel.getSecurityMode();
......
showSecurityScreen(securityMode);
}
KeyguardSecurityContainer.showSecurityScreen:
//初次启动时mCurrentSecuritySelection为SecurityMode.Invalid
private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
private void showSecurityScreen(SecurityMode securityMode) {
//判断此参数安全模式是否与当前安全模式相同,如果相同则直接返回。
if ((securityMode == mCurrentSecuritySelection)
&& (securityMode != SecurityMode.AntiTheft)) {
return;
}
//如果不同,则通知安全模式的改变
VoiceWakeupManager.getInstance().notifySecurityModeChange(
mCurrentSecuritySelection, securityMode);
KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
KeyguardSecurityView newView = getSecurityView(securityMode);//关键方法,根据安全模式获得对应的view
......
//设置相关回调
if (securityMode != SecurityMode.None) {
newView.setKeyguardCallback(mCallback);
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
}
final int childCount = mSecurityViewFlipper.getChildCount();
//寻找当前安全模式对应的view,并进行展示。(此时PIN码解锁解锁已在getSecurityView()中添加至mSecurityViewFlipper)
//到这里view的展示也到达了本文流程的终点。
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
for (int i = 0; i < childCount; i++) {
if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
mSecurityViewFlipper.setDisplayedChild(i);
break;
}
}
//更新当前的安全选择
mCurrentSecuritySelection = securityMode;
......
}
KeyguardSecurityContainer.getSecurityView()
private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);//获取安全模式对应的view id
KeyguardSecurityView view = null;
final int children = mSecurityViewFlipper.getChildCount();
//从mSecurityViewFlipper中取出此安全模式对应view id的view,按照开机初次抵达这里的情况,此时获取的view为null
for (int child = 0; child < children; child++) {
if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
break;
}
}
//根据安全模式获得对应的layoutId
int layoutId = getLayoutIdFor(securityMode);
//如果mSecurityViewFlipper还没有此view并且存在此安全模式对应的layoutId
if (view == null && layoutId != 0) {
//inflater Layout
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);//view在这里被绘制,进行各项初始化。
view = (KeyguardSecurityView) v;//
//如果是KeyguardSimPinPukMeView则需要设置phoneid,KeyguardSimPinPukMeView将根据此phoneid展示对应资源
if (view instanceof KeyguardSimPinPukMeView) {
KeyguardSimPinPukMeView pinPukView = (KeyguardSimPinPukMeView) view;
final int phoneId = mSecurityModel.getPhoneIdUsingSecurityMode(securityMode);
pinPukView.setPhoneId(phoneId);
}
//将此view添加入mSecurityViewFlipper中
mSecurityViewFlipper.addView(v);//在这里添加view至mSecurityViewFlipper
updateSecurityView(v); //更新KeyguardSecurityView
}
return view;
}
private int getSecurityViewIdForMode(SecurityMode securityMode) {
switch (securityMode) {
case Pattern: return R.id.keyguard_pattern_view;
case PIN: return R.id.keyguard_pin_view;
case Password: return R.id.keyguard_password_view;
case SimPinPukMe1:
case SimPinPukMe2:
case SimPinPukMe3:
case SimPinPukMe4:
return R.id.keyguard_sim_pin_puk_me_view ;
}
return 0;
}
protected int getLayoutIdFor(SecurityMode securityMode) {
switch (securityMode) {
case Pattern: return R.layout.keyguard_pattern_view;//手势
case PIN: return R.layout.keyguard_pin_view;//PIN码
case Password: return R.layout.keyguard_password_view;//密码解锁
case SimPinPukMe1:
case SimPinPukMe2:
case SimPinPukMe3:
case SimPinPukMe4:
return R.layout.mtk_keyguard_sim_pin_puk_me_view;//sim_pin_puk_me
default:
return 0;
}
}
到这里,view展示,其启动流程也到此结束。