環(huán)境:ubuntu14.04
基于高通的android7.1.1代碼(同aosp差別不大)
1.現(xiàn)象:第一次直接設(shè)置指紋后,然后鎖屏,不能夠直接使用指紋進(jìn)行解鎖而是提示使用密碼,pin碼,圖案等安全鎖屏方式才能進(jìn)行解鎖?
分析:手機(jī)的解鎖方式分為pin碼,圖案,密碼等,從KeyguardSecurityModel
類(lèi)中即可看出來(lái):
/**
* 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
}
指紋等生物解鎖密碼等只是一種輔助用來(lái)解鎖的手段,不能單獨(dú)存在,而且指紋注冊(cè)時(shí)必須要基于安全鎖屏方式來(lái)獲取Token
才能注冊(cè)成功.
查看代碼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
中實(shí)現(xiàn)了此接口方法:
@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()) {
//第一次重啟機(jī)器
return KeyguardSecurityView.PROMPT_REASON_RESTART;
} else if (fingerprint && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
//所需要查看問(wèn)題所在,當(dāng)之前沒(méi)有安全解鎖方式解鎖成功時(shí),指紋第一次被設(shè)置時(shí)不能使用指紋解鎖
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) {
//用戶(hù)指紋和安全解鎖方式都可以正常使用所提示的信息
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
實(shí)例化傳遞給StatusBarKeyguardViewManager
,然后在傳遞給KeyguardBouncer
mStatusBarKeyguardViewManager =
SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, mStatusBarWindowManager, container);
接下來(lái)就需要查看在KeyguardBouncer
中如何調(diào)用此方法了,查看代碼:
有兩個(gè)地方:
public void onStrongAuthStateChanged(int userId) {
//跟蹤了相關(guān)代碼,這個(gè)是在解鎖完成之后才會(huì)調(diào)用觸發(fā)
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
public void prepare() {
boolean wasInitialized = mRoot != null;
ensureView();
if (wasInitialized) {
//每次準(zhǔn)備解鎖界面時(shí)才會(huì)調(diào)用此方法,就是這個(gè)問(wèn)題所需要的時(shí)機(jī)
mKeyguardView.showPrimarySecurityScreen();
}
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
鎖屏準(zhǔn)備解鎖界面時(shí)會(huì)調(diào)用上述邏輯,那么還是要在具體實(shí)現(xiàn)看,具體實(shí)現(xiàn)類(lèi),為什么會(huì)走入對(duì)應(yīng)分支,也就是
else if (fingerprint && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {
//所需要查看問(wèn)題所在,當(dāng)之前沒(méi)有安全解鎖方式解鎖成功時(shí),指紋第一次被設(shè)置時(shí)不能使用指紋解鎖
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) {
//通過(guò)判斷這個(gè)集合里面是否有當(dāng)前用戶(hù)ID,需要查看的就是添加到集合的時(shí)機(jī)
return !mStrongAuthNotTimedOut.contains(userId);
}
查看添加集合的時(shí)機(jī)為:
//
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);
}
}
此方法是在解鎖完成之后會(huì)調(diào)用的
@Override
public void keyguardDone(boolean strongAuth) {
if (!mKeyguardDonePending) {
KeyguardViewMediator.this.keyguardDone(true /* authenticated */);
}
if (strongAuth) {
mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
}
}
這樣我們就清楚了整個(gè)流程,只有在使用了安全的解鎖方式解鎖之后才會(huì)在集合中添加當(dāng)前用戶(hù)ID,代表之后設(shè)置指紋可以正常使用,如果在之前沒(méi)有使用過(guò)安全的解鎖方式,那么就不可以直接使用生物信息解鎖,必須要使用安全解鎖,這樣在代碼里會(huì)添加當(dāng)前用戶(hù)ID,代表用安全解鎖方式認(rèn)證完畢,所以可以使用指紋了.