本文將以開(kāi)機(jī)啟動(dòng),初次展示PIN碼解鎖界面為主線,介紹KeyguardService的組織結(jié)構(gòu)并分析密碼解鎖界面的呈現(xiàn)流程。
一.開(kāi)機(jī)啟動(dòng)到PhoneWindowManager
開(kāi)機(jī)啟動(dòng)init->zygote->systemserver進(jìn)程
systemserver入口是main(),實(shí)例化systemserver對(duì)象并調(diào)用其run()方法。
在run()方法中,我們此次重點(diǎn)關(guān)注startOtherServices();
在startOtherServices()啟動(dòng)了WindowManagerService,
截取部分代碼如下:
PhoneWindowManager.WindowManagerService:
private void startOtherServices() {
WindowManagerService wm = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);//啟動(dòng)服務(wù)
ServiceManager.addService(Context.WINDOW_SERVICE, wm);//注冊(cè)到ServiceManager,供其他進(jìn)程調(diào)用
......
wm.systemReady();
}
WindowManagerService.systemReady():
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
final WindowManagerPolicy mPolicy = new PhoneWindowManager();//生成PhoneWindowManager實(shí)例
public void systemReady() {
mPolicy.systemReady();//調(diào)用PhoneWindowManager.systemReady()
}
PhoneWindowManager.systemReady():
public void systemReady() {
mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
mKeyguardDelegate.onSystemReady();//實(shí)例鎖屏代理類(lèi)并調(diào)用其onSystemReady()
二.KeyguardService的組織結(jié)構(gòu)
這里先放一張整體的流程圖,方便大家查看分析:

KeyguardServiceDelegate.onSystemReady():
protected KeyguardServiceWrapper mKeyguardService;//鎖屏服務(wù)包裝類(lèi)
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的構(gòu)造函數(shù)中賦值
mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
public void onSystemReady() {
try {
mService.onSystemReady();
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
可以看到KeyguardServiceWrapper對(duì)IKeyguardService進(jìn)行了封裝,其方法實(shí)現(xiàn)主要是對(duì)
IKeyguardService的調(diào)用。而IKeyguardService在在KeyguardServiceWrapper的構(gòu)造函數(shù)中賦值。
KeyguardServiceWrapper在哪被實(shí)例化的呢?
后頭看一下KeyguardServiceDelegate初始化的過(guò)程:
/**
* 使用bindService的方式來(lái)綁定服務(wù)。利用bindService的方式:
* 調(diào)用者與服務(wù)綁定在一起,調(diào)用者退出,服務(wù)即終止。
* ps => bind方式綁定服務(wù),服務(wù)的執(zhí)行順序?yàn)椋?* 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!)");
//通過(guò)onServiceConnected()拿到KeyguardService的Binder代理對(duì)象,并創(chuàng)建KeyguardService包裝類(lèi)
//實(shí)例化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就相當(dāng)于一個(gè)客戶(hù)端,而
KeyguardService即為服務(wù)端。
看一下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(),通過(guò)這個(gè)Binder對(duì)象,客戶(hù)端與服務(wù)端才能連接起來(lái)
}
//mBinder實(shí)例化,重寫(xiě)相關(guān)接口方法
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
@Override // Binder interface
public void onSystemReady() {
checkPermission();
mKeyguardViewMediator.onSystemReady();//實(shí)際KeyguardService調(diào)用KeyguardViewMediator的對(duì)應(yīng)方法
}
......
}
}
KeyguardViewMediator.onSystemReady()
public void onSystemReady() {
synchronized (this) {
......
doKeyguardLocked(null);//鎖屏調(diào)起的真正入口,進(jìn)行鎖屏預(yù)處理工作
......
}
}
三.KeyguardBouncer呈現(xiàn)流程
上文調(diào)用如下:
PhoneWindowManager.systemReady()->KeyguardServiceDelegate.onSystemReady()
->KeyguardServiceWrapper.onSystemReady()->KeyguardService.onSystemReady()->
KeyguardViewMediator.onSystemReady().
KeyguardViewMediator.doKeyguardLocked():
private void doKeyguardLocked(Bundle options) {
//如果其他應(yīng)用阻止我們顯示,那么就不顯示。。例如:接打電話
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;
}
......
//經(jīng)過(guò)上述判斷后,再去顯示鎖屏
showLocked(options);
}
KeyguardViewMediator.showLocked()
private void showLocked(Bundle options) {
......
//獲取鎖屏鎖,不讓cpu進(jìn)入休眠,以完整的展示鎖屏
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);//發(fā)送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);//主要是調(diào)用了這里
......
StatusBarKeyguardViewManager.show():
public void show(Bundle options) {
......
reset();
}
StatusBarKeyguardViewManager.reset():
public void reset() {
if (mShowing) {
if (mOccluded) {//是否有遮擋物,如果有就隱藏鎖屏,沒(méi)有則判斷顯示鎖屏還是密碼解鎖界面
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();//獲得當(dāng)前是哪一種安全模式
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 {
//檢查當(dāng)前sim卡的Pin/Puk/Me是否均已解鎖
for (int i = 0; i < KeyguardUtils.getNumOfPhone(); i++) {
if (isPinPukOrMeRequiredOfPhoneId(i)) {//判斷此卡是否需要進(jìn)行密碼解鎖
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;
}
}
}
//是否需要顯示防盜保護(hù)
if (AntiTheftManager.isAntiTheftPriorToSecMode(mode)) {
Log.d("KeyguardSecurityModel", "should show AntiTheft!") ;
mode = SecurityMode.AntiTheft;
}
//如果當(dāng)前安全模式不是sim卡的Pin/Puk/Me也不是防盜保護(hù),則查看是PIN碼,密碼,還是手勢(shì)
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(),此時(shí)mBouncer.needsFullscreenBouncer()條件為真,隱藏鎖屏,顯示bouncer.
mBouncer.show(true /* resetSecuritySelection */);//重置安全選擇
public void show(boolean resetSecuritySelection) {
......
show(resetSecuritySelection, false) ;
}
public void show(boolean resetSecuritySelection, boolean authenticated) {
......
if (resetSecuritySelection) {//此時(shí)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) {
//獲取當(dāng)前安全模式,上文分析過(guò)
SecurityMode securityMode = mSecurityModel.getSecurityMode();
......
showSecurityScreen(securityMode);
}
KeyguardSecurityContainer.showSecurityScreen:
//初次啟動(dòng)時(shí)mCurrentSecuritySelection為SecurityMode.Invalid
private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
private void showSecurityScreen(SecurityMode securityMode) {
//判斷此參數(shù)安全模式是否與當(dāng)前安全模式相同,如果相同則直接返回。
if ((securityMode == mCurrentSecuritySelection)
&& (securityMode != SecurityMode.AntiTheft)) {
return;
}
//如果不同,則通知安全模式的改變
VoiceWakeupManager.getInstance().notifySecurityModeChange(
mCurrentSecuritySelection, securityMode);
KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
KeyguardSecurityView newView = getSecurityView(securityMode);//關(guān)鍵方法,根據(jù)安全模式獲得對(duì)應(yīng)的view
......
//設(shè)置相關(guān)回調(diào)
if (securityMode != SecurityMode.None) {
newView.setKeyguardCallback(mCallback);
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
}
final int childCount = mSecurityViewFlipper.getChildCount();
//尋找當(dāng)前安全模式對(duì)應(yīng)的view,并進(jìn)行展示。(此時(shí)PIN碼解鎖解鎖已在getSecurityView()中添加至mSecurityViewFlipper)
//到這里view的展示也到達(dá)了本文流程的終點(diǎn)。
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
for (int i = 0; i < childCount; i++) {
if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
mSecurityViewFlipper.setDisplayedChild(i);
break;
}
}
//更新當(dāng)前的安全選擇
mCurrentSecuritySelection = securityMode;
......
}
KeyguardSecurityContainer.getSecurityView()
private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);//獲取安全模式對(duì)應(yīng)的view id
KeyguardSecurityView view = null;
final int children = mSecurityViewFlipper.getChildCount();
//從mSecurityViewFlipper中取出此安全模式對(duì)應(yīng)view id的view,按照開(kāi)機(jī)初次抵達(dá)這里的情況,此時(shí)獲取的view為null
for (int child = 0; child < children; child++) {
if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
break;
}
}
//根據(jù)安全模式獲得對(duì)應(yīng)的layoutId
int layoutId = getLayoutIdFor(securityMode);
//如果mSecurityViewFlipper還沒(méi)有此view并且存在此安全模式對(duì)應(yīng)的layoutId
if (view == null && layoutId != 0) {
//inflater Layout
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);//view在這里被繪制,進(jìn)行各項(xiàng)初始化。
view = (KeyguardSecurityView) v;//
//如果是KeyguardSimPinPukMeView則需要設(shè)置phoneid,KeyguardSimPinPukMeView將根據(jù)此phoneid展示對(duì)應(yīng)資源
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;//手勢(shì)
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展示,其啟動(dòng)流程也到此結(jié)束。