4.1 指纹认证成功回调的传递
当指纹注册完,用户进行指纹认证成功后,底层库返回结果后会调用onAuthenticated来反馈结果给receiver,在往上层反馈。
我们从BiometricsFingerprint开始分析
void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
BiometricsFingerprint::getInstance());
std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
ALOGE("Receiving callbacks before the client callback is registered.");
return;
}
const uint64_t devId = reinterpret_cast<uint64_t>(thisPtr->mDevice);
switch (msg->type) {
case FINGERPRINT_ERROR: {
int32_t vendorCode = 0;
FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
ALOGD("onError(%d)", result);
if (!thisPtr->mClientCallback->onError(devId, result, vendorCode).isOk()) {
ALOGE("failed to invoke fingerprint onError callback");
}
}
break;
case FINGERPRINT_ACQUIRED: {
int32_t vendorCode = 0;
FingerprintAcquiredInfo result =
VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
ALOGD("onAcquired(%d)", result);
if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) {
ALOGE("failed to invoke fingerprint onAcquired callback");
}
}
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)",
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining);
if (!thisPtr->mClientCallback->onEnrollResult(devId,
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining).isOk()) {
ALOGE("failed to invoke fingerprint onEnrollResult callback");
}
break;
case FINGERPRINT_TEMPLATE_REMOVED:
ALOGD("onRemove(fid=%d, gid=%d, rem=%d)",
msg->data.removed.finger.fid,
msg->data.removed.finger.gid,
msg->data.removed.remaining_templates);
if (!thisPtr->mClientCallback->onRemoved(devId,
msg->data.removed.finger.fid,
msg->data.removed.finger.gid,
msg->data.removed.remaining_templates).isOk()) {
ALOGE("failed to invoke fingerprint onRemoved callback");
}
break;
case FINGERPRINT_AUTHENTICATED:
if (msg->data.authenticated.finger.fid != 0) {
ALOGD("onAuthenticated(fid=%d, gid=%d)",
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
const uint8_t* hat =
reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
const hidl_vec<uint8_t> token(
std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
if (!thisPtr->mClientCallback->onAuthenticated(devId,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid,
token).isOk()) {
ALOGE("failed to invoke fingerprint onAuthenticated callback");
}
} else {
// Not a recognized fingerprint
if (!thisPtr->mClientCallback->onAuthenticated(devId,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid,
hidl_vec<uint8_t>()).isOk()) {
ALOGE("failed to invoke fingerprint onAuthenticated callback");
}
}
break;
case FINGERPRINT_TEMPLATE_ENUMERATING:
ALOGD("onEnumerate(fid=%d, gid=%d, rem=%d)",
msg->data.enumerated.finger.fid,
msg->data.enumerated.finger.gid,
msg->data.enumerated.remaining_templates);
if (!thisPtr->mClientCallback->onEnumerate(devId,
msg->data.enumerated.finger.fid,
msg->data.enumerated.finger.gid,
msg->data.enumerated.remaining_templates).isOk()) {
ALOGE("failed to invoke fingerprint onEnumerate callback");
}
break;
}
我们直接看FINGERPRINT_AUTHENTICATED分支。
这里关键是
thisPtr->mClientCallback->onAuthenticated(devId,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid,
token).isOk())
thisPtr就是BiometricsFingerprint,mClientCallback赋值的地方是在setNotify
//hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
Return<uint64_t> BiometricsFingerprint::setNotify(
const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
std::lock_guard<std::mutex> lock(mClientCallbackMutex);
mClientCallback = clientCallback;
// This is here because HAL 2.1 doesn't have a way to propagate a
// unique token for its driver. Subsequent versions should send a unique
// token for each call to setNotify(). This is fine as long as there's only
// one fingerprint device on the platform.
return reinterpret_cast<uint64_t>(mDevice);
}
clientCallback是一个IBiometricsFingerprintClientCallback对象,先看看IBiometricsFingerprintClientCallback的实现。
//framework/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub {
}
IBiometricsFingerprintClientCallback的实现类是HalResultController。
再来看HalResultController是如何创建的。
public static Fingerprint21 newInstance(@NonNull Context context,
@NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
final BiometricScheduler scheduler = new BiometricScheduler(
TAG, BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps),
gestureAvailabilityDispatcher);
final HalResultController controller = new HalResultController(
sensorProps.sensorId, context, handler, scheduler);
return new Fingerprint21(context, biometricStateCallback, sensorProps, scheduler,
handler, lockoutResetDispatcher, controller,
BiometricContext.getInstance(context));
}
它的创建是在Fingerprint21#newInstance中,然后传递给了Fingerprint21。
mHalResultController = controller;
在Fingerprint21的构造函数也就是把它赋值给mHalResultController。
那么我们来看看mHalResultController是怎么和hardware层联系起来的。
synchronized IBiometricsFingerprint getDaemon() {
// HAL ID for these HIDL versions are only used to determine
// if callbacks have been successfully set.
long halId = 0;
try {
halId = mDaemon.setNotify(mHalResultController);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to set callback for fingerprint HAL", e);
mDaemon = null;
}
}
@Nullable private IBiometricsFingerprint mDaemon;
答案是在getDaemon()里面,通过上节我们知道,这里mDaemon就是BiometricsFingerprint,这就调用到了BiometricsFingerprint#setNotify。
public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub {
@Override
public void onAuthenticated(long deviceId, int fingerId, int groupId,
ArrayList<Byte> token) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
return;
}
final AuthenticationConsumer authenticationConsumer =
(AuthenticationConsumer) client;
final boolean authenticated = fingerId != 0;
final Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId);
authenticationConsumer.onAuthenticated(fp, authenticated, token);
});
}
}
所以,mClientCallback->onAuthenticated实际调用的是HalResultController#onAuthenticated。
而HalResultController#onAuthenticated会从mScheduler.getCurrentClient()中拿到client,然后转化为AuthenticationConsumer对象,调用它的onAuthenticated。
首先mScheduler前面其实分析过,它的创建是在Fingerprint21#newInstance。
/**
* Get current operation <code>BaseClientMonitor</code>
* @deprecated TODO: b/229994966, encapsulate client monitors
* @return the current operation
*/
@Deprecated
@Nullable
public BaseClientMonitor getCurrentClient() {
return mCurrentOperation != null ? mCurrentOperation.getClientMonitor() : null;
}
这里getCurrentClient()最终拿到的是FingerprintAuthenticationClient。
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
// Authentication lifecycle ends either when
// 1) Authenticated == true
// 2) Error occurred (lockout or some other error)
// Note that authentication doesn't end when Authenticated == false
if (authenticated) {
mState = STATE_STOPPED;
resetFailedAttempts(getTargetUserId());
mSensorOverlays.hide(getSensorId());
} else {
mState = STATE_STARTED_PAUSED_ATTEMPTED;
final @LockoutTracker.LockoutMode int lockoutMode =
mLockoutFrameworkImpl.getLockoutModeForUser(getTargetUserId());
if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
Slog.w(TAG, "Fingerprint locked out, lockoutMode(" + lockoutMode + ")");
final int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
: BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
// Send the error, but do not invoke the FinishCallback yet. Since lockout is not
// controlled by the HAL, the framework must stop the sensor before finishing the
// client.
mSensorOverlays.hide(getSensorId());
onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
cancel();
}
}
}
这里将mState 设置为STATE_STOPPED,继续看它的父类AuthenticationClient#onAuthenticated。
//framework/base/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
getTargetUserId(), isBiometricPrompt());
final BiometricServiceBase.ServiceListener listener = getListener();
mMetricsLogger.action(mConstants.actionBiometricAuth(), authenticated);
boolean result = false;
try {
if (DEBUG) Slog.v(getLogTag(), "onAuthenticated(" + authenticated + ")"
+ ", ID:" + identifier.getBiometricId()
+ ", Owner: " + getOwnerString()
+ ", isBP: " + isBiometricPrompt()
+ ", listener: " + listener
+ ", requireConfirmation: " + mRequireConfirmation
+ ", user: " + getTargetUserId());
// Ensure authentication only succeeds if the client activity is on top or is keyguard.
boolean isBackgroundAuth = false;
if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())) {
try {
final List<ActivityManager.RunningTaskInfo> tasks =
ActivityTaskManager.getService().getTasks(1);
if (tasks == null || tasks.isEmpty()) {
Slog.e(TAG, "No running tasks reported");
isBackgroundAuth = true;
} else {
final ComponentName topActivity = tasks.get(0).topActivity;
if (topActivity == null) {
Slog.e(TAG, "Unable to get top activity");
isBackgroundAuth = true;
} else {
final String topPackage = topActivity.getPackageName();
if (!topPackage.contentEquals(getOwnerString())) {
Slog.e(TAG, "Background authentication detected, top: " + topPackage
+ ", client: " + this);
isBackgroundAuth = true;
}
}
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to get running tasks", e);
isBackgroundAuth = true;
}
}
// Fail authentication if we can't confirm the client activity is on top.
if (isBackgroundAuth) {
Slog.e(TAG, "Failing possible background authentication");
authenticated = false;
// SafetyNet logging for exploitation attempts of b/159249069.
final ApplicationInfo appInfo = getContext().getApplicationInfo();
EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
"Attempted background authentication");
}
if (authenticated) {
// SafetyNet logging for b/159249069 if constraint is violated.
if (isBackgroundAuth) {
final ApplicationInfo appInfo = getContext().getApplicationInfo();
EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
"Successful background authentication!");
}
mAlreadyDone = true;
if (listener != null) {
vibrateSuccess();
}
result = true;
if (shouldFrameworkHandleLockout()) {
resetFailedAttempts();
}
onStop();
final byte[] byteToken = new byte[token.size()];
for (int i = 0; i < token.size(); i++) {
byteToken[i] = token.get(i);
}
if (isBiometricPrompt() && listener != null) {
// BiometricService will add the token to keystore
listener.onAuthenticationSucceededInternal(mRequireConfirmation, byteToken,
isStrongBiometric());
} else if (!isBiometricPrompt() && listener != null) {
if (isStrongBiometric()) {
KeyStore.getInstance().addAuthToken(byteToken);
} else {
Slog.d(getLogTag(), "Skipping addAuthToken");
}
try {
// Explicitly have if/else here to make it super obvious in case the code is
// touched in the future.
if (!getIsRestricted()) {
listener.onAuthenticationSucceeded(
getHalDeviceId(), identifier, getTargetUserId());
} else {
listener.onAuthenticationSucceeded(
getHalDeviceId(), null, getTargetUserId());
}
} catch (RemoteException e) {
Slog.e(getLogTag(), "Remote exception", e);
}
} else {
// Client not listening
Slog.w(getLogTag(), "Client not listening");
result = true;
}
} else {
if (listener != null) {
vibrateError();
}
// Allow system-defined limit of number of attempts before giving up
final int lockoutMode = handleFailedAttempt();
if (lockoutMode != LOCKOUT_NONE && shouldFrameworkHandleLockout()) {
Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode("
+ lockoutMode + ")");
stop(false);
final int errorCode = lockoutMode == LOCKOUT_TIMED
? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
: BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
} else {
// Don't send onAuthenticationFailed if we're in lockout, it causes a
// janky UI on Keyguard/BiometricPrompt since "authentication failed"
// will show briefly and be replaced by "device locked out" message.
if (listener != null) {
if (isBiometricPrompt()) {
listener.onAuthenticationFailedInternal();
} else {
listener.onAuthenticationFailed(getHalDeviceId());
}
}
}
result = lockoutMode != LOCKOUT_NONE; // in a lockout mode
if(result) { // locked out
mAlreadyDone = true;
}
}
} catch (RemoteException e) {
Slog.e(getLogTag(), "Remote exception", e);
result = true;
}
return result;
}
如果认证结果返回但是当前不是锁屏界面,并且判断是isBackgroundAuth的时候,就会将认证解锁authenticated设置为false,这时会进行认错误震动,如果是BiometricPrompt,就回调onAuthenticationFailedInternal,否则回调onAuthenticationFailed。
如果authenticated设置为true,会进行认证成功震动,并且重置错误次数resetFailedAttempts,如果是BiometricPrompt就回调onAuthenticationSucceededInternal,否则如果是isStrongBiometric,会向KeyStore中加入认证成功的记录byteToken,最后回调onAuthenticationSucceeded。
再来看listener
final ClientMonitorCallbackConverter listener = getListener();
我们从ClientMonitorCallbackConverter的构造函数开始。
public ClientMonitorCallbackConverter(IFingerprintServiceReceiver fingerprintServiceReceiver) {
mFingerprintServiceReceiver = fingerprintServiceReceiver;
}
它的创建是在FingerprintService
//framework/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@Override // Binder call
public long authenticate(
final IBinder token,
final long operationId,
final IFingerprintServiceReceiver receiver,
final FingerprintAuthenticateOptions options) {
...
return provider.second.scheduleAuthenticate(token, operationId,
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
restricted, statsClient, isKeyguard);
}
继续看Fingerprint21#scheduleAuthenticate
//framework/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mLazyDaemon, token, requestId, listener, operationId,
restricted, options, cookie, false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mTaskStackListener, mLockoutTracker,
mUdfpsOverlayController, mSidefpsController, mUdfpsOverlay,
allowBackgroundAuthentication, mSensorProperties,
Utils.getCurrentStrength(mSensorId));
再来看FingerprintAuthenticationClient的构造函数。
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, long operationId,
boolean restricted, @NonNull FingerprintAuthenticateOptions options,
int cookie, boolean requireConfirmation, @NonNull BiometricLogger logger,
@NonNull BiometricContext biometricContext, boolean isStrongBiometric,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable ISidefpsController sidefpsController,
@Nullable IUdfpsOverlay udfpsOverlay,
boolean allowBackgroundAuthentication,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@Authenticators.Types int sensorStrength) {
super(context, lazyDaemon, token, listener, operationId, restricted,
options, cookie, requireConfirmation, logger, biometricContext,
isStrongBiometric, taskStackListener, lockoutTracker,
allowBackgroundAuthentication, false /* shouldVibrate */,
sensorStrength);
继续看父类
//framework/base/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
public AuthenticationClient(@NonNull Context context,
@NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener,
long operationId, boolean restricted, @NonNull O options,
int cookie, boolean requireConfirmation,
@NonNull BiometricLogger biometricLogger,
@NonNull BiometricContext biometricContext,
boolean isStrongBiometric,
@Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker,
boolean allowBackgroundAuthentication,
boolean shouldVibrate, int sensorStrength) {
super(context, lazyDaemon, token, listener, options.getUserId(),
options.getOpPackageName(), cookie, options.getSensorId(), shouldVibrate,
biometricLogger, biometricContext);
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;
mActivityTaskManager = getActivityTaskManager();
mBiometricManager = context.getSystemService(BiometricManager.class);
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
mAllowBackgroundAuthentication = allowBackgroundAuthentication;
mShouldUseLockoutTracker = lockoutTracker != null;
mSensorStrength = sensorStrength;
mOptions = options;
}
继续看父类
//framework/base/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
public AcquisitionClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener,
int userId,
@NonNull String owner, int cookie, int sensorId,
boolean shouldVibrate,
@NonNull BiometricLogger logger,
@NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId,
logger, biometricContext);
mPowerManager = context.getSystemService(PowerManager.class);
mShouldVibrate = shouldVibrate;
}
继续看父类
//framework/base/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
public HalClientMonitor(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@Nullable IBinder token,
@Nullable ClientMonitorCallbackConverter listener,
int userId,
@NonNull String owner, int cookie, int sensorId,
@NonNull BiometricLogger biometricLogger,
@NonNull BiometricContext biometricContext) {
super(context, token, listener, userId, owner, cookie, sensorId,
biometricLogger, biometricContext);
mLazyDaemon = lazyDaemon;
mOperationContext = new OperationContextExt(isBiometricPrompt());
}
继续看父类
//framework/base/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
/**
* @param context system_server context
* @param token a unique token for the client
* @param listener recipient of related events (e.g. authentication)
* @param userId target user id for operation
* @param owner name of the client that owns this
* @param cookie BiometricPrompt authentication cookie (to be moved into a subclass soon)
* @param sensorId ID of the sensor that the operation should be requested of
* @param logger framework stats logger
* @param biometricContext system context metadata
*/
public BaseClientMonitor(@NonNull Context context,
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
mSequentialId = sCount++;
mContext = context;
mToken = token;
mRequestId = -1;
mListener = listener;
mTargetUserId = userId;
mOwner = owner;
mCookie = cookie;
mSensorId = sensorId;
mLogger = logger;
mBiometricContext = biometricContext;
try {
if (token != null) {
token.linkToDeath(this, 0);
}
} catch (RemoteException e) {
Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
}
}
@Nullable
public final ClientMonitorCallbackConverter getListener() {
return mListener;
}
终于不用看父类了!!!
这里没有回调mListener,而是提供了一个getListener(),看来是给子类用的。
到这里,我们知道 listener.onAuthenticationSucceeded(getHalDeviceId(), null, getTargetUserId());调用的是ClientMonitorCallbackConverter的onAuthenticationSucceeded
//framework/base/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
void onAuthenticationSucceeded(int sensorId, BiometricAuthenticator.Identifier identifier,
byte[] token, int userId, boolean isStrongBiometric) throws RemoteException {
if (mSensorReceiver != null) {
mSensorReceiver.onAuthenticationSucceeded(sensorId, token);
} else if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onAuthenticationSucceeded((Face) identifier, userId,
isStrongBiometric);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onAuthenticationSucceeded((Fingerprint) identifier, userId,
isStrongBiometric);
}
}
public ClientMonitorCallbackConverter(IFingerprintServiceReceiver fingerprintServiceReceiver) {
mFingerprintServiceReceiver = fingerprintServiceReceiver;
}
而mFingerprintServiceReceiver是从FingerprintService赋值并转换的。
@Override // Binder call
public long authenticate() {
...
return provider.second.scheduleAuthenticate(token, operationId,
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
restricted, statsClient, isKeyguard);
}
继续看FingerprintManager的authenticate
final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
在FingerprintManager里面将mAuthenticationCallback存起来,并将mServiceReceiver传递给FingerprintService。
//framework/base/core/java/android/hardware/fingerprint/FingerprintManager.java
private IFingerprintServiceReceiver mServiceReceiver =
new IFingerprintServiceReceiver.Stub() {
@Override // binder call
public void onAuthenticationSucceeded(Fingerprint fp, int userId,
boolean isStrongBiometric) {
mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId,
isStrongBiometric ? 1 : 0,fp).sendToTarget();
}
}
private class MyHandler extends Handler {
@Override
public void handleMessage(android.os.Message msg) {
case MSG_AUTHENTICATION_SUCCEEDED:
sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */,
msg.arg2 == 1 /* isStrongBiometric */);
break;
}
}
private void sendAuthenticatedSucceeded(Fingerprint fp, int userId,
boolean isStrongBiometric) {
if (mAuthenticationCallback != null) {
final AuthenticationResult result =
new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric);
mAuthenticationCallback.onAuthenticationSucceeded(result);
}
}
这里mAuthenticationCallback是在FingerprintManager#authenticate中赋值的。
到这里,FingerprintManager将onAuthenticationSucceeded的消息传递到了SystemUI,开始后面的解锁流程。
4.2 指纹解锁
因此,再来看SystemUI的KeyguardUpdateMonitor中指纹注册时传递的回调的mFingerprintAuthenticationCallback。
final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
= new AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId(),
result.isStrongBiometric());
Trace.endSection();
}
};
调用handleFingerprintAuthenticated
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
mLogger.d("handleFingerprintAuthenticated()"
+ " triggered while waiting for cancellation, removing watchdog");
mHandler.removeCallbacks(mFpCancelNotReceived);
}
try {
final int userId = mUserTracker.getUserId();
if (userId != authUserId) {
mLogger.logFingerprintAuthForWrongUser(authUserId);
return;
}
if (isFingerprintDisabled(userId)) {
mLogger.logFingerprintDisabledForUser(userId);
return;
}
onFingerprintAuthenticated(userId, isStrongBiometric);
} finally {
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
}
Trace.endSection();
}
继续走onFingerprintAuthenticated(userId, isStrongBiometric);
public void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
Assert.isMainThread();
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId,
new BiometricAuthenticated(true, isStrongBiometric));
// Update/refresh trust state only if user can skip bouncer
if (getUserCanSkipBouncer(userId)) {
mTrustManager.unlockedByBiometricForUser(userId, FINGERPRINT);
}
// Don't send cancel if authentication succeeds
mFingerprintCancelSignal = null;
mLogger.logFingerprintSuccess(userId, isStrongBiometric);
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
FACE_AUTH_UPDATED_FP_AUTHENTICATED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthenticated(userId, FINGERPRINT, isStrongBiometric);
}
}
mHandler.sendMessageDelayed(mHandler.obtainMessage(
MSG_BIOMETRIC_AUTHENTICATION_CONTINUE), FINGERPRINT_CONTINUE_DELAY_MS);
// Only authenticate fingerprint once when assistant is visible
mAssistantVisible = false;
// Report unlock with strong or non-strong biometric
reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
Trace.endSection();
}
开始调用接口将解锁成功消息层层传递直至keyguard解锁,与face解锁逻辑一致。
可以看到在onFaceAuthenticated(userId)方法中调用了KeyguardUpdateMonitorCallback这个抽象类的onBiometricAuthenticated()抽象方法,而BiometricUnlockController extends KeyguardUpdateMonitorCallback,并注册了回调mUpdateMonitor.registerCallback(this)
@Override
public void onBiometricAuthenticated(int userId,
BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
if (mUpdateMonitor.isGoingToSleep()) {
mPendingAuthenticated = new PendingAuthenticated(
userId, biometricSourceType, isStrongBiometric);
Trace.endSection();
return;
}
mBiometricType = biometricSourceType;
mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH).setType(
MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(
biometricSourceType)).ifPresent(UI_EVENT_LOGGER::log);
boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
biometricSourceType, isStrongBiometric);
if (unlockAllowed) {
mKeyguardViewMediator.userActivity();
startWakeAndUnlock(biometricSourceType, isStrongBiometric);
} else {
Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
}
}
直接看startWakeAndUnlock。
public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
startWakeAndUnlock(calculateMode(biometricSourceType, isStrongBiometric));
}
public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = mode;
mHasScreenTurnedOnSinceAuthenticating = false;
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
// If we are waking the device up while we are pulsing the clock and the
// notifications would light up first, creating an unpleasant animation.
// Defer changing the screen brightness by forcing doze brightness on our window
// until the clock and the notifications are faded out.
mNotificationShadeWindowController.setForceDozeBrightness(true);
}
// During wake and unlock, we need to draw black before waking up to avoid abrupt
// brightness changes due to display state transitions.
boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
Runnable wakeUp = ()-> {
if (!wasDeviceInteractive) {
if (DEBUG_BIO_WAKELOCK) {
Log.i(TAG, "bio wakelock: Authenticated, waking up...");
}
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"android.policy:BIOMETRIC");
}
if (delayWakeUp) {
mKeyguardViewMediator.onWakeAndUnlocking();
}
Trace.beginSection("release wake-and-unlock");
releaseBiometricWakeLock();
Trace.endSection();
};
if (!delayWakeUp && mMode != MODE_NONE) {
wakeUp.run();
}
switch (mMode) {
case MODE_DISMISS_BOUNCER:
case MODE_UNLOCK_FADING:
Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING");
mKeyguardViewController.notifyKeyguardAuthenticated(
false /* strongAuth */);
Trace.endSection();
break;
case MODE_UNLOCK_COLLAPSING:
case MODE_SHOW_BOUNCER:
Trace.beginSection("MODE_UNLOCK_COLLAPSING or MODE_SHOW_BOUNCER");
if (!wasDeviceInteractive) {
mPendingShowBouncer = true;
} else {
showBouncer();
}
Trace.endSection();
break;
case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
case MODE_WAKE_AND_UNLOCK_PULSING:
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
} else if (mMode == MODE_WAKE_AND_UNLOCK){
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
} else {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
mUpdateMonitor.awakenFromDream();
}
mNotificationShadeWindowController.setNotificationShadeFocusable(false);
if (delayWakeUp) {
mHandler.postDelayed(wakeUp, mWakeUpDelay);
} else {
mKeyguardViewMediator.onWakeAndUnlocking();
}
if (mStatusBar.getNavigationBarView() != null) {
mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
Trace.endSection();
break;
case MODE_ONLY_WAKE:
case MODE_NONE:
break;
}
mStatusBar.notifyBiometricAuthModeChanged();
Trace.endSection();
}
如果当前是在或者要进入Bouncer界面,就走mKeyguardViewController.notifyKeyguardAuthenticated。
public void notifyKeyguardAuthenticated(boolean strongAuth) {
ensureView();
mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
}
@Override
public void finish(boolean strongAuth, int targetUserId) {
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
boolean deferKeyguardDone = false;
if (mDismissAction != null) {
deferKeyguardDone = mDismissAction.onDismiss();
mDismissAction = null;
mCancelAction = null;
}
if (mViewMediatorCallback != null) {
if (deferKeyguardDone) {
mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
} else {
mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
}
}
}
private void tryKeyguardDone() {
if (DEBUG) {
Log.d(TAG, "tryKeyguardDone: pending - " + mKeyguardDonePending + ", animRan - "
+ mHideAnimationRun + " animRunning - " + mHideAnimationRunning);
}
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();
} else if (!mHideAnimationRun) {
if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
mHideAnimationRun = true;
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get()
.startPreHideAnimation(mHideAnimationFinishedRunnable);
}
}
如果是MODE_WAKE_AND_UNLOCK,就走mKeyguardViewMediator.onWakeAndUnlocking()
public void onWakeAndUnlocking() {
Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking");
mWakeAndUnlocking = true;
keyguardDone();
Trace.endSection();
}
后面解锁流程就不看了,本文主要是介绍指纹相关的流程。