Android指纹录入与解锁源码解析-4 指纹解锁

时间:2024-07-15 19:42:49

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();
}

后面解锁流程就不看了,本文主要是介绍指纹相关的流程。