Android 6.0 SystemUI 鎖屏流程解析
談到鎖屏我們先來(lái)簡(jiǎn)單看下systemUI的啟動(dòng)流程
SystemUI常駐于系統(tǒng)链烈,通過(guò)Service實(shí)現(xiàn)能曾,關(guān)鍵service:SystemUIService是在SystemServer.java中啟動(dòng)笆环。
Android的啟動(dòng)分為內(nèi)核啟動(dòng)浦译,android啟動(dòng)战惊,Launcher啟動(dòng)信柿,我們的SystemServer就處于Android啟動(dòng)中钠绍,SystemUI的啟動(dòng)以下是大致流程:init->ServiceManager->Zygote->SystemServer->SystemUIService-->SystemUIApplication-->SystemUI.start(KeyguardViewMeditor,Recents等SytsemUI子類開始各司其職的正常工作起來(lái))
SystemUI具體的啟動(dòng)流程代碼可以參考博客舆声。
設(shè)計(jì)代碼
frameworks/base/packages/Keyguard
frameworks/base/packages/SystemUI
frameworks/base/policy/src/com/android/internal/policy/impl/keyguard/ KeyguardServiceWrapper.java KeyguardServiceDelegate.java frameworks/base/core/java/android/app/keyguardManager.java packages/apps/Settings/src/com/android/settings/ChooseLockGeneric.java SecuritySettings.java
鎖屏分類
那么鎖屏界面是怎樣加載到widnow顯示出來(lái)的呢?首先需要明確的是6.0分為兩類鎖屏(非安全鎖屏<滑動(dòng)鎖屏>和安全鎖屏<圖案和pin等>)
1.非安全鎖屏柳爽,稱之為notification keyguard媳握,這個(gè)類型的keyguard 已經(jīng)和statusbar融為一體,可以通過(guò)PhoneStatusBar.java對(duì)象直接進(jìn)行控制磷脯;
2.安全鎖屏蛾找,比如密碼,圖案赵誓,PIN碼打毛,PUK碼等鎖屏的鎖屏界面柿赊,通過(guò)keyguardBouncer.java進(jìn)行控制
鎖屏加載流程
非安全鎖屏加載流程
首先非安全鎖屏界面,是NotificationPanelView的一部分幻枉,在SystemUI啟動(dòng)SystemUI.start就已經(jīng)加載碰声,看下SystemUI開機(jī)啟動(dòng)流程圖
因?yàn)檫@里重點(diǎn)是鎖屏,所以我們從PhoneStatusBar.start()開啟看展辞。
PhoneStatusBar.start會(huì)調(diào)用父類BaseStatusBar的start(),繼續(xù)調(diào)用PhoneStatusBar的createAndAddWindow()奥邮,然后繼續(xù)調(diào)用addStatusBarWindow來(lái)創(chuàng)建通知鎖屏等StatusBarWindowView并加到window上。
非安全鎖屏是NotificationPanelView的一部分罗珍,而NotificationPanelView又是StatusBarWindowView的一部分洽腺,所以這樣就已經(jīng)將非安全模式加載好了,至于顯示還是隱藏就只是NotificationPanelView界面調(diào)整的問(wèn)題了覆旱,具體的View層級(jí)和控制代碼量太多蘸朋,暫不做深入分析
private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mRemoteInputController = new RemoteInputController(mStatusBarWindowManager, mHeadsUpManager); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); }
安全鎖屏加載流程
安全鎖屏SystemUI啟動(dòng)時(shí)準(zhǔn)備
上面還只是加載了非安全鎖屏界面,那安全鎖屏界面呢?實(shí)際上安全鎖屏界面也會(huì)加載到StatusBarWindowView扣唱,只不過(guò)是動(dòng)態(tài)加載和移除藕坯,并不是直接放在布局里初始化加載,我們簡(jiǎn)單看下鎖屏UI層級(jí)
在PhoneStatusBar.start()方法里加載完StatusBarWindowView后噪沙,還會(huì)調(diào)用startKeyGuard()來(lái)安全鎖屏的一些初始化準(zhǔn)備工作炼彪,這里關(guān)注的是將StatusBarWindowView作為屬性賦值給安全鎖屏的操控類KeyguardBoncer
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
??????? DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
??????? HeadsUpManager.OnHeadsUpChangedListener {
??? @Override
??? public void start() {
??????? super.start(); // calls createAndAddWindows()
??????? startKeyguard();
???? }??? private void startKeyguard() {
??????? KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
??????? //-----這里的mStatusBarWindow就是StatusBarWindowView
??????? mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
??????????????? mStatusBarWindow, mStatusBarWindowManager, mScrimController);
??????? mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
??? }
}public class KeyguardViewMediator extends SystemUI {
??? public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
??????????? ViewGroup container, StatusBarWindowManager statusBarWindowManager,
??????????? ScrimController scrimController) {
??????? //-----這里的container就是StatusBarWindowView???????
??????? mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
??????????????? statusBarWindowManager, scrimController);
??????? return mStatusBarKeyguardViewManager;
??? }
}
?
public class StatusBarKeyguardViewManager {
??? public void registerStatusBar(PhoneStatusBar phoneStatusBar,
??????????? ViewGroup container, StatusBarWindowManager statusBarWindowManager,
??????????? ScrimController scrimController) {
??????? mPhoneStatusBar = phoneStatusBar;
??????? mContainer = container;
??????? mStatusBarWindowManager = statusBarWindowManager;
??????? mScrimController = scrimController;
??????? mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
??????????????? mStatusBarWindowManager, container);
??????? mKeyguardMusicManager = KeyguardMusicManager.getInstance(mContext, this);
??? }
}public class KeyguardBouncer {
??? public KeyguardBouncer(Context context, ViewMediatorCallback callback,
??????????? LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
??????????? ViewGroup container) {
??????? mContext = context;
??????? mCallback = callback;
??????? mLockPatternUtils = lockPatternUtils;
??????? mContainer = container;//-----這樣就將StatusBarWindowView作為屬性賦值給安全鎖屏的操控類
??????? mWindowManager = windowManager;
??? }
}
安全鎖屏開機(jī)展示流程
時(shí)序圖
到現(xiàn)在為止還只是StatusBarWindowView與KeyguardBouncer關(guān)聯(lián),那安全鎖屏界面到底是什么時(shí)候加載到StatusBarWindowView從而顯示給我們呢正歼?實(shí)際上我們前面也說(shuō)了辐马,安全鎖屏界面其實(shí)是動(dòng)態(tài)的加載和移除的,從未上鎖到上鎖就會(huì)addView局义,完成全部解鎖就會(huì)removeView喜爷,比如開機(jī)完成后就會(huì)上鎖,下面我們來(lái)分析下開機(jī)展示安全鎖屏流程萄唇,首先看下時(shí)序圖:
代碼流程
開機(jī)啟動(dòng)流程其實(shí)也很復(fù)雜檩帐,但是本文重點(diǎn)在于KeyGuard鎖屏的展示,所以我們從開機(jī)啟動(dòng)調(diào)用到PhoneWindowManager的SystemReady()和SystemReady()和SystemBooted()方法開始分析另萤。
systemReady()調(diào)用systemBooted()之前湃密,至于具體的調(diào)用流程這里不做分析,大致也是SystemServer.java中main函數(shù)會(huì)調(diào)用startOtherService()方法跟下去:
那么現(xiàn)在看下去PhoneWindowManager的systemReady()和systemBooted()這兩個(gè)方法
public class PhoneWindowManager implements WindowManagerPolicy {
??? @Override
??? public void systemReady() {
??????? mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
??????? mKeyguardDelegate.onSystemReady();
??????? boolean bindKeyguardNow;
??????? 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) {
??????????? mKeyguardDelegate.bindService(mContext);
??????????? mKeyguardDelegate.onBootCompleted();
??????? }
??? }
???
??? @Override
??? public void systemBooted() {
?????? ?
??????? boolean bindKeyguardNow = false;
??????? synchronized (mLock) {
??????????? // Time to bind Keyguard; take care to only bind it once, either here if ready or
??????????? // in systemReady if not.
??????????? if (mKeyguardDelegate != null) {
??????????????? bindKeyguardNow = true;
??????????? } else {
??????????????? // Because mKeyguardDelegate is null, we know that the synchronized block in
??????????????? // systemReady didn't run yet and setting this will actually have an effect.
??????????????? mDeferBindKeyguard = true;
??????????? }
??????? }
??????? if (bindKeyguardNow) {
??????????? mKeyguardDelegate.bindService(mContext);
??????????? mKeyguardDelegate.onBootCompleted();
??????? }
?}
看代碼可知四敞,systemReady()方法里初始化KeyguardServiceDeleGate勾缭,但還不能bindService,等到systemBooted()時(shí)才能bindService,下面bindService做了些什么
public class KeyguardServiceDelegate {
??? protected KeyguardServiceWrapper mKeyguardService;
??? public void bindService(Context context) {
??????? Intent intent = new Intent();
??????? //-----config_keyguardComponent就是com.android.systemui/com.android.systemui.keyguard.KeyguardService
??????? final ComponentName keyguardComponent = ComponentName.unflattenFromString(
??????????????? resources.getString(com.android.internal.R.string.config_keyguardComponent));
??????? intent.setComponent(keyguardComponent);
??????? if (!context.bindServiceAsUser(intent, mKeyguardConnection,
??????????????? Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {}
??? }
??? private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
??????? @Override
??????? public void onServiceConnected(ComponentName name, IBinder service) {
??????????? mKeyguardService = new KeyguardServiceWrapper(mContext,
??????????????????? IKeyguardService.Stub.asInterface(service));
??????????? if (mKeyguardState.systemIsReady) {
??????????????? // If the system is ready, it means keyguard crashed and restarted.
??????????????? mKeyguardService.onSystemReady();//-----前面調(diào)用systemReady目养,所以這里成立
? ????????????? // This is used to hide the scrim once keyguard displays.
??????????????? mKeyguardService.onStartedWakingUp()
??????????????? mKeyguardService.onScreenTurningOn(
??????????????????????? new KeyguardShowDelegate(mDrawnListenerWhenConnect));
??????????????? mKeyguardService.onScreenTurnedOn();
??????????????? mDrawnListenerWhenConnect = null;
??????????? }
??????????? if (mKeyguardState.bootCompleted) {
??????????????? mKeyguardService.onBootCompleted();
??????????? }
??????????? if (mKeyguardState.occluded) {
??????????????? mKeyguardService.setOccluded(mKeyguardState.occluded);
??????????? }
??????? }
??????? @Override
??????? public void onServiceDisconnected(ComponentName name) {
??????????? if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
??????????? mKeyguardService = null;
??????? }
??? };
?}
因?yàn)閏onfig_keyguardComponent就是com.android.systemui/com.andoid.systemui.keyguard.KeyguardService,所以IKeyguardService.Stub.asInterface(service)就是KeyguardService里的private final IKeyguardService.Stub mBinder俩由,也就是KeyguardServiceWrapper里的private IKeyguardService mService,所以接著調(diào)用onSystemReady()
public class KeyguardServiceWrapper implements IKeyguardService {
??? private IKeyguardService mService;
??? public KeyguardServiceWrapper(Context context, IKeyguardService service) {
??????? mService = service;
??? }
??? @Override // Binder interface
??? public void onSystemReady() {
??????? try {
??????????? mService.onSystemReady();
??????? } catch (RemoteException e) {
??????????? Slog.w(TAG , "Remote Exception", e);
??????? }
??? }
}
于是再走到KeyguardService.mBinder.onSystemReady()
public class KeyguardService extends Service {
??? private KeyguardViewMediator mKeyguardViewMediator;
??? private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
??????? @Override // Binder interface
??????? public void onSystemReady() {
??????????? checkPermission();
??????????? mKeyguardViewMediator.onSystemReady();
??????? }
??? }
}
終于走到我們鎖屏模塊最關(guān)鍵的調(diào)度類KeyguardViewMediator癌蚁,功能上負(fù)責(zé)處理keyguard試圖的事件幻梯,鎖屏事件的入口兜畸,下面繼續(xù)KeyguardViewMediator的doKeyguardLocked()
public class KeyguardViewMediator extends SystemUI {
??? public void onSystemReady() {
??????????? doKeyguardLocked(null);
??? }
??? private void doKeyguardLocked(Bundle options) {
??????? showLocked(options);
??? }
??? private void showLocked(Bundle options) {
??????? if (DEBUG) Log.d(TAG, "showLocked");
??????? // ensure we stay awake until we are finished displaying the keyguard
??????? mShowKeyguardWakeLock.acquire();
??????? Message msg = mHandler.obtainMessage(SHOW, options);
??????? mHandler.sendMessage(msg);
??? }
??? private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
??????? @Override
??????? public void handleMessage(Message msg) {
??????????? switch (msg.what) {
??????????????? case SHOW:
??????????????????? handleShow((Bundle) msg.obj);
??????????????????? break;
??????????? }
??????? }
??? };
??? private void handleShow(Bundle options) {
??????????? mStatusBarKeyguardViewManager.show(options);
??? }
???
}
通過(guò)代碼可知,最后將show動(dòng)作交給StatusBarkeyguardViewManager來(lái)處理碘梢,實(shí)際上這類直接鎖屏相關(guān)動(dòng)作最后都會(huì)交給StatusbarKeyguardViewManager處理咬摇,StatusBarKeyguardViewManager就是keyguard的視圖管理者,包括非安全鎖屏和安全鎖屏煞躬,接著往下看
public class StatusBarKeyguardViewManager {
???? private PhoneStatusBar mPhoneStatusBar;
???? private KeyguardBouncer mBouncer;
???? /**
???? * Show the keyguard.? Will handle creating and attaching to the view manager
???? * lazily.
???? */
??? public void show(Bundle options) {
??????? mShowing = true;
??????? mStatusBarWindowManager.setKeyguardShowing(true);
??????? mScrimController.abortKeyguardFadingOut();
??????? reset();//-----show和reset動(dòng)作都會(huì)調(diào)用reset
??????? mKeyguardMusicManager.start();
??? }
??? /**
???? * Reset the state of the view.
???? */
??? public void reset() {
??????? if (mShowing) {
??????????? if (mOccluded) {
??????????????? mPhoneStatusBar.hideKeyguard();
??????????????? mPhoneStatusBar.stopWaitingForKeyguardExit();
??????????????? mBouncer.hide(false /* destroyView */);
??????????? } else {
??????????????? showBouncerOrKeyguard();//-----顯示安全鎖屏界面還是先顯示非安全鎖屏界面
??????????? }
??????????? KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
??????????? updateStates();
??????? }
??? }
??? /**
???? * Shows the notification keyguard or the bouncer depending on
???? * {@link KeyguardBouncer#needsFullscreenBouncer()}.
???? */
??? private 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();
??????? }
??? }
}
在showBouncerOrKeyguard方法里mPhoneStatusBar.hideKeyguard()和mPhoneStatusBar.showKeyguard肛鹏;控制的是非安全鎖,而mBoncer.show(true)和mBoncer.hide(false)控制的是安全鎖屏恩沛,也就是說(shuō)非安全鎖屏和安全鎖屏在這里開始分別由PhoneStatusBar和KeyguardBouncer管理在扰,前面說(shuō)了非安全鎖屏這里不做升入分析,下面重點(diǎn)看安全鎖屏雷客,安全鎖屏界面KeyguardHostView作為KeyguardBouncer的屬性直接被操控芒珠,而要不要先顯示非安全鎖屏是根據(jù)鎖屏模式來(lái)的,由于鎖屏情況太多現(xiàn)在假設(shè)是圖案解鎖搅裙,具體在往下來(lái)皱卓,根據(jù)目前場(chǎng)景來(lái)看是會(huì)走到
/**
?* A class which manages the bouncer on the lockscreen.
?*/
public class KeyguardBouncer {
??? private KeyguardHostView mKeyguardView;
??? /**
???? * @return True if and only if the security method should be shown before showing the
???? * notifications on Keyguard, like SIM PIN/PUK.
???? */
??? public boolean needsFullscreenBouncer() {
??????? ensureView();//-----a
??????? if (mKeyguardView != null) {
??????????? SecurityMode mode = mKeyguardView.getSecurityMode();
??????????? return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;//-----c
??????? }
??????? return false;
??? }
??? public void show(boolean resetSecuritySelection) {//-----實(shí)際上顯示、重置部逮、移除動(dòng)作都會(huì)調(diào)用到
??????? ensureView();//----確保安全鎖屏界面有創(chuàng)建并添加到StatusBarWindowView上娜汁,并且安全界面初始化時(shí)是不可見的INVISIBLE
??????? if (resetSecuritySelection) {//-----是否需要重置安全界面
??????????? // showPrimarySecurityScreen() updates the current security method. This is needed in
??????????? // case we are already showing and the current security method changed.
??????????? mKeyguardView.showPrimarySecurityScreen();//-----d
??????? }
??????? if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {//-----mRoot是安全鎖屏界面,當(dāng)已是可見是return,比如重置
??????????? return;
??????? }
??????? // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
??????? // Keyguard. If we need to authenticate, show the bouncer.
??????? if (!mKeyguardView.dismiss()) {//-----試圖移除鎖屏界面兄朋,比如剛上鎖存炮,安全界面還不可見//-----e
??????????? mShowingSoon = true; // Split up the work over multiple frames.
??????????? DejankUtils.postAfterTraversal(mShowRunnable);//-----安全界面設(shè)置成可見VISIBLE//-----f
??????? }
?? ?}
??? private final Runnable mShowRunnable = new Runnable() {
??????? @Override
??????? public void run() {
??????????? mRoot.setVisibility(View.VISIBLE);
??????????? mKeyguardView.onResume();
??????????? showPromptReason(mBouncerPromptReason);
??????????? mKeyguardView.startAppearAnimation();
??????????? mShowingSoon = false;
??????????? mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
??????? }
??? };
??? private void ensureView() {
??????? if (mRoot == null) {//-----安全界面跟布局,一般無(wú)鎖到有鎖初始化蜈漓,完全完成解鎖時(shí)置空
??????????? inflateView();//-----b
??????? }
??? }
??? private void inflateView() {
??????? removeView();
??????? mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
??????? mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
??????? mKeyguardView.setLockPatternUtils(mLockPatternUtils);
??????? mKeyguardView.setViewMediatorCallback(mCallback);
??????? mContainer.addView(mRoot, mContainer.getChildCount());
??????? mRoot.setVisibility(View.INVISIBLE);
??????? mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
??? }
}
接著看mKeyguardView.showPrimarySecurityScreen(),KeyguardHostView是安全鎖屏主界面,實(shí)現(xiàn)了SecrityCallBack接口宫盔,其他地方用到的SeurityCakkback其實(shí)就是KeyguardHostview
public class KeyguardHostView extends FrameLayout implements SecurityCallback {
??? private KeyguardSecurityContainer mSecurityContainer;
??????? /**
???? * Called when the view needs to be shown.
???? */
??? public void showPrimarySecurityScreen() {
??????? if (DEBUG) Log.d(TAG, "show()");
??????? mSecurityContainer.showPrimarySecurityScreen(false);
??? }
}
KeyguardSecurityContainer融虽,安全鎖屏View的容,會(huì)具體根據(jù)安全模式展示不同的View灼芭,繼續(xù)往下面
public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
??? private KeyguardSecurityViewFlipper mSecurityViewFlipper;//安全view的父布局
??? /**
???? * Shows the primary security screen for the user. This will be either the multi-selector
???? * or the user's security method.
???? * @param turningOff true if the device is being turned off
???? */
??? void showPrimarySecurityScreen(boolean turningOff) {
??????? SecurityMode securityMode = mSecurityModel.getSecurityMode();//----獲取安全模式
??????? if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
??????? showSecurityScreen(securityMode);
??? }
??? 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);//----將安全view添加到父布局<span></span>KeyguardSecurityViewFlipper從而到<span></span>KeyguardSecurityContainer上
??????????? updateSecurityView(v);
??????????? view = (KeyguardSecurityView)v;
??????? }
??????? return view;
??? }
}
到目前位置通過(guò)mSercutityViewFliper.addView(v);最終將安全view添加到StatusBarWindowView有额,但是安全鎖屏跟布局還是不可見的,所以代碼走到KeyguardBouncer的處彼绷,那么mKeyguardView.dismiss()又做了什么呢巍佑,繼續(xù)往下跟
public class KeyguardHostView extends FrameLayout implements SecurityCallback {
??? /**
???? *? Dismisses the keyguard by going to the next screen or making it gone.
???? *
???? *? @return True if the keyguard is done.
???? */
??? public boolean dismiss() {
??????? return dismiss(false);
??? }
??? @Override
??? public boolean dismiss(boolean authenticated) {
??????? return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
??? }
}
好吧,又是KeyguardSecurityContainer寄悯,當(dāng)前場(chǎng)景下參數(shù)未false萤衰,繼續(xù)往下看:
/**
???? * Shows the next security screen if there is one.
???? * @param authenticated true if the user entered the correct authentication
???? * @return true if keyguard is done
???? */
??? //-----顯示下一個(gè)安全鎖屏界面,參數(shù)很重要猜旬,參數(shù)表示是否經(jīng)過(guò)驗(yàn)證
??? boolean showNextSecurityScreenOrFinish(boolean authenticated) {
??????? if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
??????? boolean finish = false;
??????? if (mUpdateMonitor.getUserCanSkipBouncer(
??????????????? KeyguardUpdateMonitor.getCurrentUser())) {
??????????? //-----可以跳過(guò)安全鎖屏脆栋,直接完全所有鎖屏
??????????? finish = true;
??????? } else if (SecurityMode.None == mCurrentSecuritySelection) {
??????????? //當(dāng)前是非安全鎖屏(滑動(dòng))倦卖,獲取下一個(gè)鎖屏模式,如果還是非安全鎖屏(滑動(dòng)),直接完全所有鎖屏,否則顯示下一個(gè)安全鎖屏界面
??????????? SecurityMode securityMode = mSecurityModel.getSecurityMode();
??????????? if (SecurityMode.None == securityMode) {
??????????????? finish = true; // no security required
??????????? } else {
??????????????? showSecurityScreen(securityMode); // switch to the alternate security view
??????????? }
??????? } else if (authenticated) {
??????????? //-----如果是經(jīng)過(guò)驗(yàn)證的椿争,當(dāng)前的是普通的安全模式怕膛,那么完成全部解鎖,如果是pin\puk之類的第三類動(dòng)態(tài)的就繼續(xù)檢查下一個(gè)鎖屏秦踪,
??????????? //-----下一個(gè)是安全鎖屏就繼續(xù)顯示下一個(gè)安全鎖屏界面褐捻,否則完成全部解鎖
??????????? switch (mCurrentSecuritySelection) {
??????????????? case Pattern:
??????????????? case Password:
??????????????? case PIN:
??????????????????? finish = true;
??????????????????? break;
??????????????? case SimPin:
??????????????? case SimPuk:
??????????????????? // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
??????????????????? SecurityMode securityMode = mSecurityModel.getSecurityMode();
??????????????????? if (securityMode != SecurityMode.None
??????????????????????????? || !mLockPatternUtils.isLockScreenDisabled(
??????????????????????????? KeyguardUpdateMonitor.getCurrentUser())) {
??????????????????????? showSecurityScreen(securityMode);
??????????????????????? /* SPRD:add PIN verify success prompt @{ */
??????????????????????? KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
??????????????????????? if (oldView != null) {
??????????????????????????? oldView.onPause();
??????????????????????? }
??????????????????????? /* @} */
??????????????????? } else {
??????????????????????? finish = true;
??????????????????? }
??????????????????? break;
??????????????? default:
??????????????????? Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
??????????????????? showPrimarySecurityScreen(false);
??????????????????? break;
??????????? }
??????? }
??????? if (finish) {
??????????? //-----完成了全部解鎖,下面要開始rm安全界面等一些操作椅邓,mSecurityCallback就是KeyguardHostView
??????????? mSecurityCallback.finish();
??????? }
??????? return finish;
??? }
當(dāng)前場(chǎng)景下都不滿足柠逞,直接返回false,那么代碼繼續(xù)走到KeyguardBouncer的處希坚,也就是把安全鎖屏根布局設(shè)置為可見mRoot.setVisibility(View.VISIBLE);最終鎖屏控件都已加載到StatusBarWindowView上且可見
鎖屏調(diào)用入口
其他場(chǎng)景边苹,如解鎖,滅屏等按照上面的思路結(jié)構(gòu)都很容易分析就不再贅述裁僧,調(diào)用入口目前如下幾種情況个束;
1KeyguardSecurityCallBack.dismiss(true)-->KeyguardSecurityContainer.SecurityCallback.dismiss(true)-->實(shí)際上對(duì)象就是KeyguardHostView.dismiss(true)-->......這中一般是解鎖了安全鎖屏onClick里
2ViewMeditorCallback-->實(shí)際對(duì)象就是KeyguardViewMeditor.mViewMeditorCallback
這種一般是應(yīng)用內(nèi)直接調(diào)用,比如添加手機(jī)防盜解鎖聊疲,受到上鎖廣播時(shí)直接調(diào)用showLocked(null)或resetStatLocked()
3茬底、KeyguardServiceDelegate-->綁定KeyguardService? ?????
<permission android:name="com.android.systemui.permission.SELF" ??????????? android:protectionLevel="signature" />? ????
signature:這種權(quán)限級(jí)別,只有當(dāng)發(fā)請(qǐng)求的應(yīng)用和接收此請(qǐng)求的應(yīng)用使用同一簽名文件获洲,并且聲明了該權(quán)限才會(huì)授權(quán)阱表,并且是默認(rèn)授權(quán),不會(huì)提示用戶授權(quán)? ???? 這種一般是frameworks通過(guò)binder服務(wù)調(diào)用贡珊,如開機(jī)上鎖最爬,滅屏上鎖等?
4、通過(guò)屬性android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUAR ????????????????????? android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKE ???
第三方應(yīng)用一般因?yàn)闄?quán)限問(wèn)題通過(guò)屬性來(lái)控制消除非安全鎖屏或界面顯示在鎖之上
總結(jié)
最后關(guān)于鎖屏再總結(jié)一下:
ui層級(jí)圖
UI時(shí)序圖
1门岔、鎖屏分兩類:非安全鎖屏(如滑動(dòng)鎖屏)和安全鎖屏(滑動(dòng)鎖屏)
2爱致、他們都會(huì)加載到StatusBarWindowView上,而StatusBarWindowView在又會(huì)加載到window上從而顯示出來(lái)
3寒随、不同的是: 非安全鎖屏在PanelHolder上糠悯,是StatusBarWindowView布局的一部分,所以隨著開機(jī)加載systemui時(shí)就會(huì)加載上去妻往,通過(guò)展開折疊等布局控制來(lái)顯示與否 而安全鎖屏是KeyguardHostView互艾,它并不是StatusBarWindowView原有布局的一部分,而是根據(jù)上鎖和解鎖實(shí)際情況來(lái)動(dòng)態(tài)加載和移除以及設(shè)置可見與不可見來(lái)顯示與否讯泣,第一次加載是在完成開機(jī)動(dòng)畫觸屏可顯示時(shí)