一、关于锁屏的模式
锁屏方式有两种,如下为定义方式
/**
* 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);
}