先从息屏或者按power键指纹监听开始分析
1.当灭屏后会从PhoneWindowManager.java执行startedGoingToSleep()方法:
// Called on the PowerManager's Notifier thread.
@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
mGoingToSleep = true;
mRequestedOrGoingToSleep = true;
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
}
2.然后KeyguardServiceDelegate.java-->onStartedGoingToSleep()
public void onStartedGoingToSleep(int why) {
if (mKeyguardService != null) {
mKeyguardService.onStartedGoingToSleep(why);
}
mKeyguardState.offReason = why;
mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
}
3.在从KeyguardServiceWrapper.java -->onStartedGoingToSleep()
@Override
public void onStartedGoingToSleep(int reason) {
try {
mService.onStartedGoingToSleep(reason);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
4.mService的实例对象为IKeyguardService,而KeyguardService.java搭建了IKeyguardService.Stub()桥梁,可以直接通信,且实现了onStartedGoingToSleep().
@Override // Binder interface
public void onStartedGoingToSleep(int reason) {
checkPermission();
mKeyguardViewMediator.onStartedGoingToSleep(reason);
mKeyguardLifecyclesDispatcher.dispatch(
KeyguardLifecyclesDispatcher.STARTED_GOING_TO_SLEEP);
}
5.KeyguardViewMediator.java-->onStartedGoingToSleep()
public void onStartedGoingToSleep(int why) {
...
KeyguardUpdateMonitor.getInstance(mContext).dispatchStartedGoingToSleep(why);
notifyStartedGoingToSleep();
}
6.发送MSG_STARTED_GOING_TO_SLEEP消息,处理handleStartedGoingToSleep()方法,即:KeyguardUpdateMonitor.java-->dispatchStartedGoingToSleep()
public void dispatchStartedGoingToSleep(int why) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0));
}
7.处理handleStartedGoingToSleep方法:KeyguardUpdateMonitor.java-->handleStartedGoingToSleep()
protected void handleStartedGoingToSleep(int arg1) {
clearFingerprintRecognized();
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onStartedGoingToSleep(arg1);
}
}
mGoingToSleep = true;
updateFingerprintListeningState();//这行代码就是停止监听,还是开始监听指纹的,里面有判断
}
8.KeyguardUpdateMonitor.java-->updateFingerprintListeningState()
private void updateFingerprintListeningState() {
// If this message exists, we should not authenticate again until this message is
// consumed by the handler
if (mHandler.hasMessages(MSG_FINGERPRINT_AUTHENTICATION_CONTINUE)) {
return;
}
mHandler.removeCallbacks(mRetryFingerprintAuthentication);
boolean shouldListenForFingerprint = shouldListenForFingerprint();
if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
stopListeningForFingerprint();//停止监听
} else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
&& shouldListenForFingerprint) {
startListeningForFingerprint();//开始监听,一般监听会走这
}
}
9.KeyguardUpdateMonitor.java-->startListeningForFingerprint()
private void startListeningForFingerprint() {
if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
}
}
10.mAuthenticationCallback是FingerprintManager.java的一个回调接口,当指纹有状态反馈上层是时会触发
private FingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
};
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId());
Trace.endSection();
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFingerprintHelp(helpMsgId, helpString.toString());
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFingerprintAcquired(acquireInfo);
}
};
11.进入到FingerprintManager.java方法authenticate:FingerprintManager.java-->authenticate()
@RequiresPermission(USE_FINGERPRINT)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Log.w(TAG, "authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
}
}
if (mService != null) try {
useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
long sessionId = crypto != null ? crypto.getOpId() : 0;
mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
mContext.getOpPackageName()); //mServiceReceiver这个广播很重要,接收从底层反馈的有关指纹的一些状态
} catch (RemoteException e) {
Log.w(TAG, "Remote exception while authenticating: ", e);
if (callback != null) {
// Though this may not be a hardware issue, it will cause apps to give up or try
// again later.
callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
}
}
}
12.FingerprintService.java-->authenticate()
@Override // Binder call
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
final boolean restricted = isRestricted();
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
callingUserId)) {
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
mHandler.post(new Runnable() {
@Override
public void run() {
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
// Get performance stats object for this user.
HashMap
= (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
PerformanceStats stats = pmap.get(mCurrentUserId);
if (stats == null) {
stats = new PerformanceStats();
pmap.put(mCurrentUserId, stats);
}
mPerformanceStats = stats;
startAuthentication(token, opId, callingUserId, groupId, receiver,
flags, restricted, opPackageName);
}
});
}
13.FingerprintService.java-->startAuthentication()
private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
IFingerprintServiceReceiver receiver, int flags, boolean restricted,
String opPackageName) {
updateActiveGroup(groupId, opPackageName);
if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
@Override
public int handleFailedAttempt() {
mFailedAttempts++;
mTimedLockoutCleared = false;
final int lockoutMode = getLockoutMode();
if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
mPerformanceStats.permanentLockout++;
} else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
mPerformanceStats.lockout++;
}
// Failing multiple times will continue to push out the lockout time
if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
scheduleLockoutReset();
return lockoutMode;
}
return AuthenticationClient.LOCKOUT_NONE;
}
@Override
public void resetFailedAttempts() {
FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */);
}
@Override
public void notifyUserActivity() {
FingerprintService.this.userActivity();
}
@Override
public IBiometricsFingerprint getFingerprintDaemon() {
return FingerprintService.this.getFingerprintDaemon();
}
};
int lockoutMode = getLockoutMode();
if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
Slog.v(TAG, "In lockout mode(" + lockoutMode +
") ; disallowing authentication");
int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
if (!client.onError(errorCode, 0 /* vendorCode */)) {
Slog.w(TAG, "Cannot send permanent lockout message to client");
}
return;
}
startClient(client, true /* initiatedByClient */);
}
14.开始监听:FingerprintService.java-->startClient()
private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
ClientMonitor currentClient = mCurrentClient;
if (currentClient != null) {
if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
if (currentClient instanceof InternalEnumerateClient ||
currentClient instanceof InternalRemovalClient) {
// This condition means we're currently running internal diagnostics to
// remove extra fingerprints in the hardware and/or the software
// TODO: design an escape hatch in case client never finishes
}
else {
currentClient.stop(initiatedByClient);
}
mPendingClient = newClient;
mHandler.removeCallbacks(mResetClientState);
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
} else if (newClient != null) {
mCurrentClient = newClient;
if (DEBUG) Slog.v(TAG, "starting client "
+ newClient.getClass().getSuperclass().getSimpleName()
+ "(" + newClient.getOwnerString() + ")"
+ ", initiatedByClient = " + initiatedByClient + ")");
notifyClientActiveCallbacks(true);
newClient.start();//开始监听指纹状态
}
}
15.AuthenticationClient.java-->start()
/**
* Start authentication
*/
@Override
public int start() {
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "start authentication: no fingerprint HAL!");
return ERROR_ESRCH;
}
try {
final int result = daemon.authenticate(mOpId, getGroupId());//这行代码是跟底层打交道的,当把指纹的一些参数传给底层,底层处理后返回一个状态,result=0表示处理完成,开始监听
if (result != 0) {
Slog.w(TAG, "startAuthentication failed, result=" + result);
MetricsLogger.histogram(getContext(), "fingeprintd_auth_start_error", result);
onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
return result;
}
if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating...");
} catch (RemoteException e) {
Slog.e(TAG, "startAuthentication failed", e);
return ERROR_ESRCH;
}
return 0; // success
}
16.灭屏时开始监听的流程完成,当有指纹解锁时,会执行
AuthenticationClient.java-->onAuthenticated()
@Override
public boolean onAuthenticated(int fingerId, int groupId) {
boolean result = false;
boolean authenticated = fingerId != 0;
IFingerprintServiceReceiver receiver = getReceiver();
if (receiver != null) {
try {
MetricsLogger.action(getContext(), MetricsEvent.ACTION_FINGERPRINT_AUTH,
authenticated);
if (!authenticated) {
receiver.onAuthenticationFailed(getHalDeviceId());
} else {
if (DEBUG) {
Slog.v(TAG, "onAuthenticated(owner=" + getOwnerString()
+ ", id=" + fingerId + ", gp=" + groupId + ")");
}
Fingerprint fp = !getIsRestricted()
? new Fingerprint("" /* TODO */, groupId, fingerId, getHalDeviceId())
: null;
receiver.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId());
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify Authenticated:", e);
result = true; // client failed
}
} else {
result = true; // client not listening
}
if (!authenticated) {
if (receiver != null) {
vibrateError();
}
// allow system-defined limit of number of attempts before giving up
int lockoutMode = handleFailedAttempt();
if (lockoutMode != LOCKOUT_NONE) {
try {
Slog.w(TAG, "Forcing lockout (fp driver code should do this!), mode(" +
lockoutMode + ")");
stop(false);
int errorCode = lockoutMode == LOCKOUT_TIMED ?
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
receiver.onError(getHalDeviceId(), FingerprintManager.FINGERPRINT_ERROR_FORCING_LOCKOUT, 0 /* vendorCode */);//Add By [email protected] 2018/1/20 Defect:5880186
receiver.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify lockout:", e);
}
}
result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
} else {
if (receiver != null) {
vibrateSuccess();
}
result |= true; // we have a valid fingerprint, done
resetFailedAttempts();
}
return result;
}
当解锁成功,会执行 vibrateSuccess();,解锁失败会执行vibrateError();