环境:ubuntu14.04
基于高通的android7.1.1代码(同aosp差别不大)
1.现象:第一次直接设置指纹后,然后锁屏,不能够直接使用指纹进行解锁而是提示使用密码,pin码,图案等安全锁屏方式才能进行解锁?
分析:手机的解锁方式分为pin码,图案,密码等,从KeyguardSecurityModel
类中即可看出来:
/**
* The different types of security available.
* @see KeyguardSecurityContainer#showSecurityScreen
*/
public enum SecurityMode {
Invalid, // NULL state
None, // No security enabled
Pattern, // Unlock by drawing a pattern.
Password, // Unlock by entering an alphanumeric password
PIN, // Strictly numeric password
SimPin, // Unlock by entering a sim pin.
SimPuk // Unlock by entering a sim puk
}
指纹等生物解锁密码等只是一种辅助用来解锁的手段,不能单独存在,而且指纹注册时必须要基于安全锁屏方式来获取Token
才能注册成功.
查看代码ViewMediatorCallback
接口为:
/**
* @return one of the reasons why the bouncer needs to be shown right now and the user can't use
* his normal unlock method like fingerprint or trust agents. See
* {@link KeyguardSecurityView#PROMPT_REASON_NONE},
* {@link KeyguardSecurityView#PROMPT_REASON_RESTART} and
* {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}.
*/
int getBouncerPromptReason();
在KeyguardViewMediator
中实现了此接口方法:
@Override
public int getBouncerPromptReason() {
int currentUser = ActivityManager.getCurrentUser();
boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser);
boolean fingerprint = mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser);
boolean any = trust || fingerprint;
KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
mUpdateMonitor.getStrongAuthTracker();
int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
//第一次重启机器
return KeyguardSecurityView.PROMPT_REASON_RESTART;
} else if (fingerprint && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
//所需要查看问题所在,当之前没有安全解锁方式解锁成功时,指纹第一次被设置时不能使用指纹解锁
return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
} else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
//用户指纹和安全解锁方式都可以正常使用所提示的信息
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
}
return KeyguardSecurityView.PROMPT_REASON_NONE;
}
ViewMediatorCallback
实例化传递给StatusBarKeyguardViewManager
,然后在传递给KeyguardBouncer
mStatusBarKeyguardViewManager =
SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, mStatusBarWindowManager, container);
接下来就需要查看在KeyguardBouncer
中如何调用此方法了,查看代码:
有两个地方:
public void onStrongAuthStateChanged(int userId) {
//跟踪了相关代码,这个是在解锁完成之后才会调用触发
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
public void prepare() {
boolean wasInitialized = mRoot != null;
ensureView();
if (wasInitialized) {
//每次准备解锁界面时才会调用此方法,就是这个问题所需要的时机
mKeyguardView.showPrimarySecurityScreen();
}
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
锁屏准备解锁界面时会调用上述逻辑,那么还是要在具体实现看,具体实现类,为什么会走入对应分支,也就是
else if (fingerprint && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
//所需要查看问题所在,当之前没有安全解锁方式解锁成功时,指纹第一次被设置时不能使用指纹解锁
return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
}
/**
* @return true if the user hasn't use strong authentication (pattern, PIN, password) since a
* while and thus can't unlock with fingerprint, false otherwise
*/
public boolean hasFingerprintUnlockTimedOut(int userId) {
//通过判断这个集合里面是否有当前用户ID,需要查看的就是添加到集合的时机
return !mStrongAuthNotTimedOut.contains(userId);
}
查看添加集合的时机为:
//
public void reportSuccessfulStrongAuthUnlockAttempt() {
mStrongAuthNotTimedOut.add(sCurrentUser);
scheduleStrongAuthTimeout();
if (mFpm != null) {
byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
mFpm.resetTimeout(token);
}
}
此方法是在解锁完成之后会调用的
@Override
public void keyguardDone(boolean strongAuth) {
if (!mKeyguardDonePending) {
KeyguardViewMediator.this.keyguardDone(true /* authenticated */);
}
if (strongAuth) {
mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
}
}
这样我们就清楚了整个流程,只有在使用了安全的解锁方式解锁之后才会在集合中添加当前用户ID,代表之后设置指纹可以正常使用,如果在之前没有使用过安全的解锁方式,那么就不可以直接使用生物信息解锁,必须要使用安全解锁,这样在代码里会添加当前用户ID,代表用安全解锁方式认证完毕,所以可以使用指纹了.