一、關於鎖屏的模式
鎖屏方式有兩種,如下為定義方式
/** * Either a lock screen (an informational keyguard screen), or an unlock * screen (a means for unlocking the device) is shown at any given time. */ enum Mode { LockScreen, UnlockScreen }
其中,LockScreen是預設的解鎖方式,一般稱之為“解鎖”介面;UnlockScreen一般稱之為“開鎖”介面。
它們之間是並列的關係,也就是在進入解鎖後會判斷是哪一種case,然後進入,而UnlockScreen並不是最終的一種case,它又細分為如下幾種情況:
/** * The different types screens available for {@link Mode#UnlockScreen}. * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode() */ enum UnlockMode { /** * Unlock by drawing a pattern. */ Pattern, /** * Unlock by entering a sim pin. */ SimPin, /** * Unlock by entering a sim2 pin. */ Sim2Pin, /** * Unlock by entering an account's login and password. */ Account, /** * Unlock by entering a password or PIN */ Password, /** * Unknown (uninitialized) value */ Unknown }
一共有五種UnlockScreen方式,很簡單,不用多解釋。
二、getInitialMode方法
此方法是為了擷取初始的鎖屏方式,返回的結果是Mode模式中的一種--LockScreen或者UnlockScreen。而對於UnlockScreen模式,並沒有給出具體是哪種方式:pin,password,或者pattern等,沒有給出。這會在另一個方法中進行判斷。
private Mode getInitialMode() { if (stuckOnLockScreenBecauseSimMissing()) { return Mode.LockScreen; } else { if (!isSecure() || mShowLockBeforeUnlock) { return Mode.LockScreen; } else { return Mode.UnlockScreen; } }}
當sim卡不存在時,當使用者沒有選擇安全的方式(不安全意味著當前鎖屏方式是滑動解鎖,而非pin、password、pattern等),當顯示UnlockScreen前需要首先顯示LockScreen時,那麼返回LockScreen;否則返回UnlockScreen。
三、getUnlockMode方法
此方法能夠擷取到當前應該處於UnlockScreen下的哪一種解鎖方式,它會返回五種UnlockMode中的一種。
注意的是,擷取解鎖方式時是有優先順序的。源碼如下:
private UnlockMode getUnlockMode() { final IccCard.State simState = mUpdateMonitor.getSimState(Phone.GEMINI_SIM_1); final IccCard.State sim2State = mUpdateMonitor.getSimState(Phone.GEMINI_SIM_2); UnlockMode currentMode = UnlockMode.Unknown; if (simState == IccCard.State.PIN_REQUIRED && !mUpdateMonitor.getPINDismissFlag(Phone.GEMINI_SIM_1, true) || (simState == IccCard.State.PUK_REQUIRED && !mUpdateMonitor.getPINDismissFlag(Phone.GEMINI_SIM_1, false))){ currentMode = UnlockMode.SimPin; } else if (sim2State == IccCard.State.PIN_REQUIRED && !mUpdateMonitor.getPINDismissFlag(Phone.GEMINI_SIM_2, true) || (sim2State == IccCard.State.PUK_REQUIRED && !mUpdateMonitor.getPINDismissFlag(Phone.GEMINI_SIM_2, false))){ currentMode = UnlockMode.Sim2Pin; } else { final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality(); switch (mode) { case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: currentMode = UnlockMode.Password; break; case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: // "forgot pattern" button is only available in the pattern mode... if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) { currentMode = UnlockMode.Account; } else { currentMode = UnlockMode.Pattern; } break; default: throw new IllegalStateException("Unknown unlock mode:" + mode); } } return currentMode;}
預設是UnlockMode.Unknown
優先順序最高的是UnlockMode.SimPin,然後是UnlockMode.Sim2Pin,再是其它的幾種
private final KeyguardUpdateMonitor mUpdateMonitor;
這個KeyguardUpdateMonitor能夠監測當前手機的狀態,並提供了getSimState,它能夠返回當前sim卡的狀態,sim卡有多個狀態,在IccCard.java中有定義
public enum State { UNKNOWN, ABSENT, PIN_REQUIRED, PUK_REQUIRED, NETWORK_LOCKED, READY, NOT_READY, PERM_DISABLED;}
這裡我們只對PIN_REQUIRED和PUK_REQUIRED這兩個狀態進行討論。
inal int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
對於其它幾種情況,應該是有個位置來記錄這些mode的,但是我沒有找到,猜測是在資料庫中。
四、updateScreen方法
private void updateScreen(Mode mode, boolean force) { mMode = mode; /* **調用recreateLockScreen方法需要兩步驗證,任何一步不能通過都不會調用該方法 **第一步:當前解鎖方式為LockScreen,或者需要Show Lock Before Unlock,這一步就通過了 **第二步:其它方法調用updateScreen時通過force指明強制調用,或者LockScreen仍為空白,還未建立,這一步就通過了 */ // Re-create the lock screen if necessary if (mode == Mode.LockScreen || mShowLockBeforeUnlock) { if (force || mLockScreen == null) { recreateLockScreen(); } } // Re-create the unlock screen if necessary. This is primarily required to properly handle // SIM state changes. This typically happens when this method is called by reset() if (mode == Mode.UnlockScreen) { final UnlockMode unlockMode = getUnlockMode(); if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) { boolean restartFaceLock = stopFaceLockIfRunning(); recreateUnlockScreen(unlockMode); if (restartFaceLock) activateFaceLockIfAble(); } } /* **mLockScreen和mUnlockScreen分別代表LockScreen和UnlockScreen **goneScreen和visibleScreen則分別代表消失的和可見的,應該各選其一,同一時刻只有一個是可見的,且另一個是消失的 */ // visibleScreen should never be null final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen; final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen; // do this before changing visibility so focus isn't requested before the input // flag is set mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput()); if (mScreenOn) { if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) { ((KeyguardScreen) goneScreen).onPause(); } if (visibleScreen.getVisibility() != View.VISIBLE) { ((KeyguardScreen) visibleScreen).onResume(); } } if (goneScreen != null) { goneScreen.setVisibility(View.GONE); } visibleScreen.setVisibility(View.VISIBLE); requestLayout();}
五、recreateLockScreen方法
private void recreateLockScreen() { /* **如果mLockScreen已經存在,那麼這時就處於強制再建立mLockScreen的狀態 **分別調用onPause、cleanUp方法,然後再removeView掉,之後再重新建立,設定可見,並添加到ViewGroup中 **recreateUnlockScreen方法與此方法類似 */ if (mLockScreen != null) { ((KeyguardScreen) mLockScreen).onPause(); ((KeyguardScreen) mLockScreen).cleanUp(); removeView(mLockScreen); } mLockScreen = createLockScreen(); mLockScreen.setVisibility(View.INVISIBLE); addView(mLockScreen);}