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

1 指纹的启动流程

我们直接从kernel启动开始看。

1.1 指纹驱动的启动

Linux内核开始启动,初始化各种软硬件环境,加载驱动程序,挂载根文件系统,在系统文件中寻找init.rc文件,并启动init进程。Kernel中,加载指纹驱动,根据传入的dts信息创建设备节点,注册设备。

1.2 hal服务启动

然后在Init启动后,初始化和启动属性服务,并且启动Zygote进程。然后找到android.hardware.biometrics.fingerprint@2.1-service.rc,启动android.hardware.biometrics.fingerprint@2.1-service,会去open fingerprint.deault.so,等待与上层通信。

service vendor.fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service
    # "class hal" causes a race condition on some devices due to files created
    # in /data. As a workaround, postpone startup until later in boot once
    # /data is mounted.
    class late_start
    user system
    group system input uhid
    task_profiles ServiceCapacityLow

会使位于系统vendor/bin/hw下的android.hardware.biometrics.fingerprint@2.1-service(以下简称2.1 bin)开机自启动,启动后会注册2.1 service,该bin服务对应的代码在:hardware/interfaces/biometrics/fingerprint/2.1/default/service.cpp。

int main() {
    android::sp<IBiometricsFingerprint> bio = BiometricsFingerprint::getInstance();

    configureRpcThreadpool(1, true /*callerWillJoin*/);

    if (bio != nullptr) {
        if (::android::OK != bio->registerAsService()) {
            return 1;
        }
    } else {
        ALOGE("Can't create instance of BiometricsFingerprint, nullptr");
    }

    joinRpcThreadpool();

    return 0; // should never get here
}

整个注册过程只有两步,首先实例化传入的 IBiometricsFingerprint 接口对象,然后通过 registerAsService 将服务注册到 hwservicemanager。

这里BiometricsFingerprint后面会分析。

1.3 Fingerprintservice启动

等待Zygote进程启动,创建java虚拟机并为java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。

SystemServer进程启动,启动Binder线程池和SystemServiceManager,并且启动各种系统服务。会启动Fingerprintservice。

//framework/base/services/java/com/android/server/SystemServer.java
private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog();
    ...
    startOtherServices(t);
    ...
}

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
	...
    final boolean hasFeatureFingerprint =
        mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
    if (hasFeatureFingerprint) {
        t.traceBegin("StartFingerprintSensor");
        final FingerprintService fingerprintService =
            mSystemServiceManager.startService(FingerprintService.class);
        t.traceEnd();
    }
}

再来看SystemServiceManager#startService

//framework/base/services/core/java/com/android/server/SystemServiceManager.java
public SystemService startService(String className) {
    final Class<SystemService> serviceClass = loadClassFromLoader(className,
         this.getClass().getClassLoader());
    return startService(serviceClass);
}

private static Class<SystemService> loadClassFromLoader(String className,
                                                        ClassLoader classLoader) {
    try {
        return (Class<SystemService>) Class.forName(className, true, classLoader);
    }
}

public <T extends SystemService> T startService(Class<T> serviceClass) {
    final T service;
    try {
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        service = constructor.newInstance(mContext);
    }
    ...
    startService(service);
    return service;
}

public void startService(@NonNull final SystemService service) {
    // Check if already started
    String className = service.getClass().getName();
    if (mServiceClassnames.contains(className)) {
        Slog.i(TAG, "Not starting an already started service " + className);
        return;
    }
    mServiceClassnames.add(className);

    // Register it.
    mServices.add(service);

    // Start it.
    long time = SystemClock.elapsedRealtime();
    try {
        service.onStart();
    } catch (RuntimeException ex) {
        throw new RuntimeException("Failed to start service " 
                                   + service.getClass().getName()
                                   + ": onStart threw an exception", ex);
    }
    warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}

可以看到会反射创建这个类的构造方法并把它添加到services中,接着执行这个类的onStart方法.

因此,我们来看FingerprintService的onStart方法。

@Override
public void onStart() {
    publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
}

最终调用到了SystemService#publishBinderService

//framework/base/services/core/java/com/android/server/SystemService.java
protected final void publishBinderService(String name, IBinder service,
                                          boolean allowIsolated, int dumpPriority) {
    ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}

注册的服务接口

/** Receives the incoming binder calls from FingerprintManager. */
final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() {
    @Override // Binder call
    public long enroll() {}

    @Override // Binder call
    public long authenticate(){}

}

这样就可以提供指纹服务给客户端。

1.4 总结

具有系统权限的client下发注册命令->FingerprintManager收到命令->FingerprintService收到命令->(2.1 service)BiometricsFingerprint收到命令->(fingerprint.default.so)Fingerprint.cpp收到命令->指纹CA收到命令->指纹TA收到命令->SPI采集数据\算法进行注册等
在这里插入图片描述

2 指纹录入

指纹录入的入口在Settings中,其重要负责指纹录入一些UI的加载和一些录入动画的逻辑。

2.1 指纹录入

先来看录入的入口类FingerprintEnrollEnrolling

public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling
 - public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
  - public abstract class BiometricEnrollBase extends InstrumentedActivity
   - public abstract class InstrumentedActivity extends ObservableActivity 
    - public class ObservableActivity extends FragmentActivity
	 - androidx.fragment.app.FragmentActivity;

从继承关系可以看到FingerprintEnrollEnrolling与人脸基本是一样的。

//packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
/**
 * Activity which handles the actual enrolling for fingerprint.
 */
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}

同样的,FingerprintEnrollEnrolling也是一个activity。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    final FingerprintManager fingerprintManager =
        getSystemService(FingerprintManager.class);
    final List<FingerprintSensorPropertiesInternal> props =
        fingerprintManager.getSensorPropertiesInternal();
    mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType();
    if (mCanAssumeUdfps) {
        if (BiometricUtils.isReverseLandscape(getApplicationContext())) {
            setContentView(R.layout.udfps_enroll_enrolling_land);
        } else {
            setContentView(R.layout.udfps_enroll_enrolling);
        }
        setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
    } else {
        setContentView(R.layout.fingerprint_enroll_enrolling);
        setDescriptionText(
          R.string.security_settings_fingerprint_enroll_start_message);
    }
    ....
}

我们看这里的startEnrollment

@Override
public void onEnterAnimationComplete() {
    super.onEnterAnimationComplete();
 
    if (mCanAssumeUdfps) {
        startEnrollment();
    }

    mAnimationCancelled = false;
    startIconAnimation();
}

这里调到了FingerprintEnrollSidecar#startEnrollment录入的方法

@Override
protected void startEnrollment() {
    super.startEnrollment();

    if (mToken == null) {
        Log.e(TAG, "Null hardware auth token for enroll");
        onEnrollmentError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                          getString(R.string.fingerprint_intro_error_unknown));
        return;
    }

    mFingerprintManager.enroll(
        mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
        mEnrollReason);
}

startEnrollment里面直接调用FingerprintManager#enroll。我们先看看这个mEnrollmentCallback有啥。

private FingerprintManager.EnrollmentCallback mEnrollmentCallback
    = new FingerprintManager.EnrollmentCallback() {

    @Override
    public void onEnrollmentProgress(int remaining) {
        FingerprintEnrollSidecar.super.onEnrollmentProgress(remaining);
    }

    @Override
    public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
        FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
    }

    @Override
    public void onEnrollmentError(int errMsgId, CharSequence errString) {
        FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
    }
};

这里主要是录入进度、提示信息、录入错误等回调。

再来看frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java的enrol,到这里就正式进入系统流程了。

/**
 * Request fingerprint enrollment. This call warms up the fingerprint hardware
 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
 * {@link EnrollmentCallback} object. It terminates when
 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
 * which point the object is no longer valid. The operation can be canceled by using the
 * provided cancel object.
 * @param token a unique token provided by a recent creation or verification of device
 * credentials (e.g. pin, pattern or password).
 * @param cancel an object that can be used to cancel enrollment
 * @param flags optional flags
 * @param userId the user to whom this fingerprint will belong to
 * @param callback an object to receive enrollment events
 * @hide
 */
@RequiresPermission(MANAGE_FINGERPRINT)
public void enroll(byte [] token, CancellationSignal cancel, int flags,
                   int userId, EnrollmentCallback callback) {
    if (userId == UserHandle.USER_CURRENT) {
        userId = getCurrentUserId();
    }
    if (callback == null) {
        throw new IllegalArgumentException("Must supply an enrollment callback");
    }

    if (cancel != null) {
        if (cancel.isCanceled()) {
            Slog.w(TAG, "enrollment already canceled");
            return;
        } else {
            cancel.setOnCancelListener(new OnEnrollCancelListener());
        }
    }

    if (mService != null) try {
        mEnrollmentCallback = callback;
        mService.enroll(mToken, token, userId, mServiceReceiver, flags,
                        mContext.getOpPackageName());
    } catch (RemoteException e) {
        Slog.w(TAG, "Remote exception in enroll: ", e);
        if (callback != null) {
            // Though this may not be a hardware issue, 
            // it will cause apps to give up or try again later.
            callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
                    getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
                                   0 /* vendorCode */));
        }
    }
}

这里直接调用的FaceService#enroll,继续往下看。

/**
 * Receives the incoming binder calls from FingerprintManager.
 */
@Override // Binder call
public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
                   final IFingerprintServiceReceiver receiver, final int flags,
                   final String opPackageName) {
    checkPermission(MANAGE_FINGERPRINT);

    final boolean restricted = isRestricted();
    final int groupId = userId; // default group for fingerprint enrollment
    final EnrollClientImpl client = new EnrollClientImpl(getContext(),
               mDaemonWrapper, mHalDeviceId, token, 
               new ServiceListenerImpl(receiver), mCurrentUserId, groupId,
               cryptoToken, restricted, opPackageName, 
               new int[0] /* disabledFeatures */, ENROLL_TIMEOUT_SEC) {
        @Override
        public boolean shouldVibrate() {
            return true;
        }

        @Override
        protected int statsModality() {
            return FingerprintService.this.statsModality();
        }
    };

    enrollInternal(client, userId);
}

这里先检查有没有MANAGE_FINGERPRINT的权限,然后向构建了EnrollClientImpl,我们知道后面接收录入进度全靠这个类了。

这里重点是enrollInternal。

//framework/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
/**
 * Calls from the Manager. These are still on the calling binder's thread.
 */

protected void enrollInternal(EnrollClientImpl client, int userId) {
    if (hasReachedEnrollmentLimit(userId)) {
        return;
    }

    // Group ID is arbitrarily set to parent profile user ID. It just represents
    // the default biometrics for the user.
    if (!isCurrentUserOrProfile(userId)) {
        return;
    }

    mHandler.post(() -> {
        startClient(client, true /* initiatedByClient */);
    });
}

enrollInternal首先检查指纹录入的数量是否达到限制。

@Override
protected boolean hasReachedEnrollmentLimit(int userId) {
    final int limit = getContext().getResources().getInteger(
        com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
    final int enrolled = FingerprintService.this.getEnrolledTemplates(userId).size();
    if (enrolled >= limit) {
        Slog.w(TAG, "Too many fingerprints registered");
        return true;
    }
    return false;
}

对比的方法是将res配置的数量和已经录入的进行对比。

<!-- For performance and storage reasons, limit the number of fingerprints per user -->
<integer name="config_fingerprintMaxTemplatesPerUser">5</integer>

从res可以看到,对于指纹来说,这个最大配置个数为5。

最后从binder线程,切换到主线程中执行startClient。

/**
 * Calls the HAL to switch states to the new task. If there's already a current task,
 * it calls cancel() and sets mPendingClient to begin when the current task finishes
 * ({@link BiometricConstants#BIOMETRIC_ERROR_CANCELED}).
 *
     * @param newClient the new client that wants to connect
     * @param initiatedByClient true for authenticate, remove and enroll
     */
    @VisibleForTesting
    void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
            if (DEBUG) Slog.v(getTag(), "request stop current client " +
                    currentClient.getOwnerString());
            // This check only matters for FingerprintService, since enumerate may call back
            // multiple times.
            if (currentClient instanceof InternalEnumerateClient
                    || currentClient instanceof InternalRemovalClient) {
                // This condition means we're currently running internal diagnostics to
                // remove extra templates in the hardware and/or the software
                // TODO: design an escape hatch in case client never finishes
                if (newClient != null) {
                    Slog.w(getTag(), "Internal cleanup in progress but trying to start client "
                            + newClient.getClass().getSuperclass().getSimpleName()
                            + "(" + newClient.getOwnerString() + ")"
                            + ", initiatedByClient = " + initiatedByClient);
                }
            } else {
                currentClient.stop(initiatedByClient);

                // Only post the reset runnable for non-cleanup clients. Cleanup clients should
                // never be forcibly stopped since they ensure synchronization between HAL and
                // framework. Thus, we should instead just start the pending client once cleanup
                // finishes instead of using the reset runnable.
                mHandler.removeCallbacks(mResetClientState);
                mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
            }
            mPendingClient = newClient;
        } else if (newClient != null) {
            // For BiometricPrompt clients, do not start until
            // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
            // modalities are ready before initiating authentication.
            if (newClient instanceof AuthenticationClient) {
                AuthenticationClient client = (AuthenticationClient) newClient;
                if (client.isBiometricPrompt()) {
                    if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie());
                    mCurrentClient = newClient;
                    if (mBiometricService == null) {
                        mBiometricService = IBiometricService.Stub.asInterface(
                                ServiceManager.getService(Context.BIOMETRIC_SERVICE));
                    }
                    try {
                        mBiometricService.onReadyForAuthentication(client.getCookie(),
                                client.getRequireConfirmation(), client.getTargetUserId());
                    } catch (RemoteException e) {
                        Slog.e(getTag(), "Remote exception", e);
                    }
                    return;
                }
            }

            // We are not a BiometricPrompt client, start the client immediately
            mCurrentClient = newClient;
            startCurrentClient(mCurrentClient.getCookie());
        }
    }

这里如果已经有task,就先cancel调当前的,然后将newClient设置到mPendingClient,并设置一个3s的延迟消息来延迟执行mPendingClient,最后执行startCurrentClient。

protected void startCurrentClient(int cookie) {
    if (mCurrentClient == null) {
        Slog.e(getTag(), "Trying to start null client!");
        return;
    }

    if (DEBUG) Slog.v(getTag(), "starting client "
                      + mCurrentClient.getClass().getSuperclass().getSimpleName()
                      + "(" + mCurrentClient.getOwnerString() + ")"
                      + " targetUserId: " + mCurrentClient.getTargetUserId()
                      + " currentUserId: " + mCurrentUserId
                      + " cookie: " + cookie + "/" + mCurrentClient.getCookie());

    if (cookie != mCurrentClient.getCookie()) {
        Slog.e(getTag(), "Mismatched cookie");
        return;
    }

    int status = mCurrentClient.start();
    if (status == 0) {
        notifyClientActiveCallbacks(true);
    } else {
        mCurrentClient.onError(getHalDeviceId(), BIOMETRIC_ERROR_HW_UNAVAILABLE,
                               0 /* vendorCode */);
        removeClient(mCurrentClient);
    }
}

还是把mCurrentClient的对象传进去了。然后是 mCurrentClient.start()。

//frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java
@Override
public int start() {
    mEnrollmentStartTimeMs = System.currentTimeMillis();
    try {
        final ArrayList<Integer> disabledFeatures = new ArrayList<>();
        for (int i = 0; i < mDisabledFeatures.length; i++) {
            disabledFeatures.add(mDisabledFeatures[i]);
        }

        final int result = getDaemonWrapper().enroll(
            mCryptoToken, getGroupId(), mTimeoutSec,disabledFeatures);
        if (result != 0) {
            Slog.w(getLogTag(), "startEnroll failed, result=" + result);
            mMetricsLogger.histogram(mConstants.tagEnrollStartError(), result);
            onError(getHalDeviceId(),
                    BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                    0 /* vendorCode */);
            return result;
        }
    } catch (RemoteException e) {
        Slog.e(getLogTag(), "startEnroll failed", e);
    }
    return 0; // success
}

EnrollClient#start方法会通过getDaemonWrapper().enroll调用底层,调用底层的指纹库,底层库返回结果后会调用onEnrollResult来反馈结果receiver,再往上层反馈。这就是指纹的录制流程。

2.2 录入进度

在onEnrollResult中当remaining等于0的时候完成录制,调用addBiometricForUser。

FingerprintManager.java中注册了 IFingerprintServiceReceiver,实现onEnrollResult方法发送 MSG_ENROLL_RESULT

//frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java  
private IFingerprintServiceReceiver mServiceReceiver = 
    new IFingerprintServiceReceiver.Stub() {
    @Override // binder call
    public void onEnrollResult(long deviceId, int fingerId, int groupId,
                               int remaining) {
        mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
           new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
    }
}

private class MyHandler extends Handler {
    @Override
    public void handleMessage(android.os.Message msg) {
        switch (msg.what) {
            case MSG_ENROLL_RESULT:
                sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                break;
        }
    }
}

private void sendEnrollResult(Fingerprint fp, int remaining) {
    if (mEnrollmentCallback != null) {
        mEnrollmentCallback.onEnrollmentProgress(remaining);
    }
}

​ 在前面FingerprintEnrollEnrolling类中的onEnrollmentProgressChange(int steps, int remaining)更新录入进度的方法中用通过传递进来的remaining来获取实际的进度;最后当进度条达到最大值时打开录入结束界launchFinish(mToken)

///packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
    updateProgress(true /* animate */);
    updateTitleAndDescription();
    clearError();
    animateFlash();
    ...
}

这里更新了进度条、背景图、提示语等,具体的就不看了。

2.3 Android 12流程

上面的流程中,Android高版本上有一些差异,我们从FingerprintService开始。

@Override // Binder call
public void enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken,
     final int userId, final IFingerprintServiceReceiver receiver,
     final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) {
    Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);

    final Pair<Integer, ServiceProvider> provider = getSingleProvider();
    if (provider == null) {
        Slog.w(TAG, "Null provider for enroll");
        return;
    }

    provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
            receiver, opPackageName, enrollReason, mFingerprintStateCallback);
}       

这里provider.second.scheduleEnroll我们一层一层拆解,先看getSingleProvider

@Nullable
private Pair<Integer, ServiceProvider> getSingleProvider() {
    final List<FingerprintSensorPropertiesInternal> properties =
        getSensorProperties();
    if (properties.isEmpty()) {
        Slog.e(TAG, "No providers found");
        return null;
    }

    // Theoretically we can just return the first provider, 
    // but maybe this is easier to understand.
    final int sensorId = properties.get(0).sensorId;
    for (ServiceProvider provider : mServiceProviders) {
        if (provider.containsSensor(sensorId)) {
            return new Pair<>(sensorId, provider);
        }
    }

    Slog.e(TAG, "Provider not found");
    return null;
}

可以看到,getSingleProvider是一个Pair<Integer, ServiceProvider>,所以provider.second就是去取Pair的第二个元素,也就是ServiceProvider。getSingleProvider就是去找到匹配的ServiceProvider。它是从mServiceProviders中去找的,那么mServiceProviders是什么时候赋值的呢?

private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
    for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
        final Fingerprint21 fingerprint21;
        if ((Build.IS_USERDEBUG || Build.IS_ENG) 
            && getContext().getResources().getBoolean(R.bool.allow_test_udfps)
            && Settings.Secure.getIntForUser(getContext().getContentResolver(),
            Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
                                             UserHandle.USER_CURRENT) != 0) {
            fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
                hidlSensor, mLockoutResetDispatcher,mGestureAvailabilityDispatcher);
        } else {
            fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor,
                     mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
        }
        mServiceProviders.add(fingerprint21);
    }
}

private void addAidlProviders() {
    final String[] instances =
        ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
    if (instances == null || instances.length == 0) {
        return;
    }
    for (String instance : instances) {
        final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
        final IFingerprint fp = IFingerprint.Stub.asInterface(Binder.allowBlocking(
            ServiceManager.waitForDeclaredService(fqName)));
        if (fp == null) {
            Slog.e(TAG, "Unable to get declared service: " + fqName);
            continue;
        }
        try {
            final SensorProps[] props = fp.getSensorProps();
            final FingerprintProvider provider =
                new FingerprintProvider(getContext(), props, instance,
                       mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
            mServiceProviders.add(provider);
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
        }
    }
}

这里有AIDL和HIDL的两种实现,我们选HIDL实现来看,它实际上就是调用Fingerprint21对象实例。

/**
 * Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or
 * its extended minor versions.
 */
public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider {
     @Override
    public void scheduleEnroll(int sensorId, @NonNull IBinder token,
                       @NonNull byte[] hardwareAuthToken, int userId,
                       @NonNull IFingerprintServiceReceiver receiver, 
                       @NonNull String opPackageName,
                       @FingerprintManager.EnrollReason int enrollReason,
                       @NonNull FingerprintStateCallback fingerprintStateCallback) {
        mHandler.post(() -> {
            scheduleUpdateActiveUserWithoutHandler(userId);

            final FingerprintEnrollClient client = new FingerprintEnrollClient(
                mContext, mLazyDaemon, token,
                new ClientMonitorCallbackConverter(receiver), userId,
                hardwareAuthToken, opPackageName,
                FingerprintUtils.getLegacyInstance(mSensorId),
                ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId,
                mUdfpsOverlayController, mSidefpsController, enrollReason);
            mScheduler.scheduleClientMonitor(client, 
              new BaseClientMonitor.Callback() {
              @Override
              public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
                  fingerprintStateCallback.onClientStarted(clientMonitor);
              }

              @Override
              public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
                                           boolean success) {
                  fingerprintStateCallback.onClientFinished(clientMonitor, success);
                  if (success) {
                      // Update authenticatorIds
                      scheduleUpdateActiveUserWithoutHandler(
                          clientMonitor.getTargetUserId(), true /* force */);
                  }
              }
              });
        });
    }
}

直接看mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback()。mScheduler是一个BiometricScheduler对象,实际上是调用类BiometricScheduler下的方法scheduleClientMonitor。

/**
 * Adds a {@link BaseClientMonitor} to the pending queue
 *
 * @param clientMonitor        operation to be scheduled
 * @param clientCallback optional callback, invoked when the client state changes.
 */
public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
                   @Nullable BaseClientMonitor.Callback clientCallback) {
    // If the incoming operation should interrupt preceding clients, 
    // mark any interruptable pending clients as canceling. 
    // Once they reach the head of the queue, the scheduler will
    // send ERROR_CANCELED and skip the operation.
    if (clientMonitor.interruptsPrecedingClients()) {
        for (Operation operation : mPendingOperations) {
            if (operation.mClientMonitor instanceof Interruptable
                && operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
                Slog.d(getTag(), "New client incoming, marking pending client as canceling: " + operation.mClientMonitor);
                operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
            }
        }
    }

    mPendingOperations.add(new Operation(clientMonitor, clientCallback));
    Slog.d(getTag(), "[Added] " + clientMonitor
           + ", new queue size: " + mPendingOperations.size());
 
    // If the new operation should interrupt preceding clients, and if the current operation is
    // cancellable, start the cancellation process.
    if (clientMonitor.interruptsPrecedingClients()
        && mCurrentOperation != null
        && mCurrentOperation.mClientMonitor instanceof Interruptable
        && mCurrentOperation.mState == Operation.STATE_STARTED) {
        Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
        cancelInternal(mCurrentOperation);
    }

    startNextOperationIfIdle();
}

我们先直接看startNextOperationIfIdle

protected void startNextOperationIfIdle() {
    if (mCurrentOperation != null) {
        Slog.v(getTag(), "Not idle, current operation: " + mCurrentOperation);
        return;
    }
    if (mPendingOperations.isEmpty()) {
        Slog.d(getTag(), "No operations, returning to idle");
        return;
    }

    mCurrentOperation = mPendingOperations.poll();
    final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;
    Slog.d(getTag(), "[Polled] " + mCurrentOperation);

    // If the operation at the front of the queue has been marked for cancellation, send
    // ERROR_CANCELED. No need to start this client.
    if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
        Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation);
        if (!(currentClient instanceof Interruptable)) {
            throw new IllegalStateException("Mis-implemented client or scheduler, "
                                            + "trying to cancel non-interruptable operation: " + mCurrentOperation);
        }

        final Interruptable interruptable = (Interruptable) currentClient;
        interruptable.cancelWithoutStarting(getInternalCallback());
        // Now we wait for the client to send its FinishCallback, which kicks off the next
        // operation.
        return;
    }

    if (mGestureAvailabilityDispatcher != null
        && mCurrentOperation.mClientMonitor instanceof AcquisitionClient) {
        mGestureAvailabilityDispatcher.markSensorActive(
            mCurrentOperation.mClientMonitor.getSensorId(),
            true /* active */);
    }

    // Not all operations start immediately. BiometricPrompt waits for its operation
    // to arrive at the head of the queue, before pinging it to start.
    final boolean shouldStartNow = currentClient.getCookie() == 0;
    if (shouldStartNow) {
        if (mCurrentOperation.isUnstartableHalOperation()) {
            final HalClientMonitor<?> halClientMonitor =
                (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
            // Note down current length of queue
            final int pendingOperationsLength = mPendingOperations.size();
            final Operation lastOperation = mPendingOperations.peekLast();
            Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
                   + ". Last pending operation: " + lastOperation);

            // For current operations, 1) unableToStart, which notifies the caller-side, then
            // 2) notify operation's callback, to notify applicable system service that the
            // operation failed.
            halClientMonitor.unableToStart();
            if (mCurrentOperation.mClientCallback != null) {
                mCurrentOperation.mClientCallback.onClientFinished(
                    mCurrentOperation.mClientMonitor, false /* success */);
            }
            // Then for each operation currently in the pending queue at the time of this
            // failure, do the same as above. Otherwise, it's possible that something like
            // setActiveUser fails, but then authenticate (for the wrong user) is invoked.
            for (int i = 0; i < pendingOperationsLength; i++) {
                final Operation operation = mPendingOperations.pollFirst();
                if (operation == null) {
                    Slog.e(getTag(), "Null operation, index: " + i
                           + ", expected length: " + pendingOperationsLength);
                    break;
                }
                if (operation.isHalOperation()) {
                    ((HalClientMonitor<?>) operation.mClientMonitor).unableToStart();
                }
                if (operation.mClientCallback != null) {
                    operation.mClientCallback.onClientFinished(operation.mClientMonitor,
                                                               false /* success */);
                }
                Slog.w(getTag(), "[Aborted Operation] " + operation);
            }

            // It's possible that during cleanup a new set of operations came in. We can try to
            // run these. A single request from the manager layer to the service layer may
            // actually be multiple operations (i.e. updateActiveUser + authenticate).
            mCurrentOperation = null;
            startNextOperationIfIdle();
        } else {
            Slog.d(getTag(), "[Starting] " + mCurrentOperation);
            currentClient.start(getInternalCallback());
            mCurrentOperation.mState = Operation.STATE_STARTED;
        }
    } else {
        try {
            mBiometricService.onReadyForAuthentication(currentClient.getCookie());
        } catch (RemoteException e) {
            Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
        }
        Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
        mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE;
    }
}

这段比较长,先看currentClient.start(getInternalCallback());

要知道下一步怎么走,我们需要知道是怎么来的。

mCurrentOperation = mPendingOperations.poll();
final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;

mCurrentOperation想从mPendingOperations中取到的,这个在前面scheduleClientMonitor中看到过。

mPendingOperations.add(new Operation(clientMonitor, clientCallback));
Slog.d(getTag(), "[Added] " + clientMonitor
       + ", new queue size: " + mPendingOperations.size());

Operation(
    @NonNull BaseClientMonitor clientMonitor,
    @Nullable BaseClientMonitor.Callback callback
) {
    this(clientMonitor, callback, STATE_WAITING_IN_QUEUE);
}

所以,上面currentClient就是clientMonitor的实例,而clientMonitor从前面可以知道,是从scheduleClientMonitor传递过来的。

public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
                                  @Nullable BaseClientMonitor.Callback clientCallback)

那我们只能回头去看看这个clientMonitor怎么来的。

final FingerprintEnrollClient client = new FingerprintEnrollClient(
                mContext, mLazyDaemon, token,
                new ClientMonitorCallbackConverter(receiver), userId,
                hardwareAuthToken, opPackageName,
                FingerprintUtils.getLegacyInstance(mSensorId),
                ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId,
                mUdfpsOverlayController, mSidefpsController, enrollReason);

可以看到,它是在Fingerprint21的scheduleEnroll方法定义的。

到这里我们就明白了,currentClient.start(getInternalCallback());实际调用的是FingerprintEnrollClient的start方法。

public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint> implements Udfps 

但是在FingerprintEnrollClient类中我们并没有看到有start方法,因此,我们在其父类中找找看。

@Override
public void start(@NonNull Callback callback) {
    super.start(callback);

    if (hasReachedEnrollmentLimit()) {
        Slog.e(TAG, "Reached enrollment limit");
        callback.onClientFinished(this, false /* success */);
        return;
    }
 
    mEnrollmentStartTimeMs = System.currentTimeMillis();
    startHalOperation();
}

果然,在父类EnrollClient中有start方法,直接看startHalOperation()。

 @Override
protected void startHalOperation() {
    mSensorOverlays.show(getSensorId(), getOverlayReasonFromEnrollReason(mEnrollReason), this);

    BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
    try {
        mCancellationSignal = getFreshDaemon().enroll(
            HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
    } catch (RemoteException e) {
        Slog.e(TAG, "Remote exception when requesting enroll", e);
        onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
                0 /* vendorCode */);
        mCallback.onClientFinished(this, false /* success */);
    }
}

这个startHalOperation是调用的FingerprintEnrollClient#startHalOperation

然后是getFreshDaemon().enroll(HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));

//frameworks/base/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
/**
 * Abstract {@link BaseClientMonitor} implementation that supports HAL operations.
 * @param <T> HAL template
 */
public abstract class HalClientMonitor<T> extends BaseClientMonitor {
    /**
      * Interface that allows ClientMonitor subclasses to retrieve a fresh instance to the HAL.
     */
    public interface LazyDaemon<T> {
    /**
      * @return A fresh instance to the biometric HAL
      */
      T getDaemon();
    }
    
    /**
     * Starts the HAL operation specific to the ClientMonitor subclass.
     */
    protected abstract void startHalOperation();
    
    protected final LazyDaemon<T> mLazyDaemon;
    
    /**
    * @param context    system_server context
    * @param lazyDaemon pointer for lazy retrieval of the HAL
    * @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 statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants
    * @param statsAction   One of {@link BiometricsProtoEnums} ACTION_* constants
    * @param statsClient   One of {@link BiometricsProtoEnums} CLIENT_* constants
    */
    public HalClientMonitor(@NonNull Context context, 
              @NonNull LazyDaemon<T> lazyDaemon,@Nullable IBinder token, 
              @Nullable ClientMonitorCallbackConverter listener, int userId,
              @NonNull String owner, int cookie, int sensorId, int statsModality,
              int statsAction, int statsClient) {
        super(context, token, listener, userId, owner, cookie, sensorId,
              statsModality, statsAction, statsClient);
        mLazyDaemon = lazyDaemon;
    }
    
    @Nullable
    public T getFreshDaemon() {
        return mLazyDaemon.getDaemon();
    }
}

这里,实际上是跨进程调用远程对象BiometricsFingerprint.cpp下的方法enroll方法。

Return<RequestStatus> BiometricsFingerprint::enroll(
    const hidl_array<uint8_t, 69>& hat, uint32_t gid, uint32_t timeoutSec) {
    const hw_auth_token_t* authToken =
        reinterpret_cast<const hw_auth_token_t*>(hat.data());
    return ErrorFilter(mDevice->enroll(mDevice, authToken, gid, timeoutSec));
}

到这里,指纹录入流程,已经关联到指纹模组了,这里不再继续。

2.2 Android 12录入进度

​ 我们接着前面分析,这里从下往上再来看,首先在BiometricsFingerprint里面

///hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
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_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;
    }
}

那么mClientCallback是怎么来的呢,在前面setNotify

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是什么时候赋值的,它是在Fingerprint21里面。

 //frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
synchronized IBiometricsFingerprint getDaemon() {
    if (mDaemon != null) {
        return mDaemon;
    }
    try {
        mDaemon = IBiometricsFingerprint.getService();
    }
    // 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;
    }
}

而mHalResultController是在 Fingerprint21的构造函数里面赋值的,

private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) {
    ...
    fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor,
    ...
}

先看看 Fingerprint21.newInstance

public static Fingerprint21 newInstance(@NonNull Context context,
              @NonNull FingerprintSensorPropertiesInternal sensorProps,
              @NonNull LockoutResetDispatcher lockoutResetDispatcher,
              @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
    final Handler handler = new Handler(Looper.getMainLooper());
    final BiometricScheduler scheduler = new BiometricScheduler(TAG,                        BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps),                       gestureAvailabilityDispatcher);
    final HalResultController controller = new HalResultController(
        sensorProps.sensorId,context, handler, scheduler);
    return new Fingerprint21(context, sensorProps, scheduler, handler,
                             lockoutResetDispatcher, controller);
}

原来是在这里创建的HalResultController。

public static class HalResultController extends IBiometricsFingerprintClientCallback.Stub {
    @Override
    public void onEnrollResult(long deviceId, int fingerId, int groupId, 
                               int remaining) {
        mHandler.post(() -> {
            final BaseClientMonitor client = mScheduler.getCurrentClient();
            if (!(client instanceof FingerprintEnrollClient)) {
                Slog.e(TAG, "onEnrollResult for non-enroll client: "
                       + Utils.getClientName(client));
                return;
            }
            
            final int currentUserId = client.getTargetUserId();
            final CharSequence name = FingerprintUtils.getLegacyInstance(mSensorId)
                .getUniqueName(mContext, currentUserId);
            final Fingerprint fingerprint = new Fingerprint(
                name, groupId, fingerId, deviceId);
  
            final FingerprintEnrollClient enrollClient = 
                (FingerprintEnrollClient) client;
            enrollClient.onEnrollResult(fingerprint, remaining);
        });
    }
}

HalResultController是Fingerprint21的静态内部类,内部实现了onEnrollResult

回到notify里面的!thisPtr->mClientCallback->onEnrollResult ,如此一来,就是调用HalResultController的onEnrollResult。

看最后的enrollClient.onEnrollResult(fingerprint, remaining);

先看看enrollClient是怎么来的。它是在HalResultController的构造函数传进来的,而scheduler是在Fingerprint21.newInstance中构造出来的, 它是一个BiometricScheduler对象。

///frameworks/base/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
/**
 * @return the current operation
 */
public BaseClientMonitor getCurrentClient() {
    if (mCurrentOperation == null) {
        return null;
    }
    return mCurrentOperation.mClientMonitor;
}

而mCurrentOperation又是前面BiometricSchedulerstartNextOperationIfIdle

//frameworks/base/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
protected void startNextOperationIfIdle() {
    mCurrentOperation = mPendingOperations.poll();
}
//
public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
                   @Nullable BaseClientMonitor.Callback clientCallback) {
    startNextOperationIfIdle();
}

,上面的enrollClient是在前面的方法scheduleEnroll中传进来的,实际上就是FingerprintEnrollClient

继续追踪 FingerprintEnrollClient下的onEnrollResult 方法

@Override
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
    super.onEnrollResult(identifier, remaining);

    mUdfpsHelper.onEnrollmentProgress(getSensorId(), remaining,
                                      mUdfpsOverlayController);

    if (remaining == 0) {
        UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
        SidefpsHelper.hideOverlay(mSidefpsController);
    }
}

先来看看录入指纹的进度条的逻辑controller.onEnrollmentProgress 。

public static void onEnrollmentProgress(int sensorId, int remaining,
            @Nullable IUdfpsOverlayController udfpsOverlayController) {
    if (udfpsOverlayController == null) {
        return;
    }
    try {
        udfpsOverlayController.onEnrollmentProgress(sensorId, remaining);
    } catch (RemoteException e) {
        Slog.e(TAG, "Remote exception when sending onEnrollmentProgress", e);
    }
}

这里的mUdfpsOverlayController是在FingerprintEnrollClient构造函数里面赋值的,而FingerprintEnrollClient初始化是在Fingerprint21#scheduleEnroll。

@Override
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
    mUdfpsOverlayController = controller;
}

赋值是通过setUdfpsOverlayController,直接到了FingerprintService。

@Override
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
    Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
 
    for (ServiceProvider provider : mServiceProviders) {
        provider.setUdfpsOverlayController(controller);
    }
}

继续往上到FingerprintManager。

@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) {
    if (mService == null) {
        Slog.w(TAG, "setUdfpsOverlayController: no fingerprint service");
        return;
    }
 
    try {
        mService.setUdfpsOverlayController(controller);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

最终,发现设置的源头是SystemUI。

//frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
public UdfpsController(@NonNull Context context, ) {
    mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
}

public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
    @Override
    public void onEnrollmentProgress(int sensorId, int remaining) {
         mFgExecutor.execute(() -> {
             if (mServerRequest == null) {
                 Log.e(TAG, "onEnrollProgress received but serverRequest is null");
                 return;
             }
             mServerRequest.onEnrollmentProgress(remaining);
         });
    }
}

FingerprintEnrollClient下的onEnrollResult 方法继续看看FingerprintEnrollClient的父类。

///frameworks/base/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
    if (mShouldVibrate) {
        vibrateSuccess();
    }

    final ClientMonitorCallbackConverter listener = getListener();
    try {
        if (listener != null) {
            listener.onEnrollResult(identifier, remaining);
        }
    } catch (RemoteException e) {
        Slog.e(TAG, "Remote exception", e);
    }
 
    if (remaining == 0) {
        mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(),
                                            identifier);
        logOnEnrolled(getTargetUserId(), 
                      System.currentTimeMillis() - mEnrollmentStartTimeMs,
                      true /* enrollSuccessful */);
        mCallback.onClientFinished(this, true /* success */);
    }
    notifyUserActivity();
}
///frameworks/base/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java
void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)
    throws RemoteException {
    if (mFaceServiceReceiver != null) {
        mFaceServiceReceiver.onEnrollResult((Face) identifier, remaining);
    } else if (mFingerprintServiceReceiver != null) {
        mFingerprintServiceReceiver.onEnrollResult(
            (Fingerprint) identifier, remaining);
    }
}

public ClientMonitorCallbackConverter(
    IFingerprintServiceReceiver fingerprintServiceReceiver) {
    mFingerprintServiceReceiver = fingerprintServiceReceiver;
}

看看ClientMonitorCallbackConverter构造的地方,在Fingerprint21。

 @Override
 public void scheduleEnroll(int sensorId, @NonNull IBinder token,
       @NonNull byte[] hardwareAuthToken, int userId,
       @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,{

       final FingerprintEnrollClient client = new FingerprintEnrollClient(
            mContext, mLazyDaemon, token, 
           new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
           opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
           ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId, mUdfpsOverlayController,
           mSidefpsController, enrollReason);
}

这里直接到FingerprintService的enroll。然后到FingerprintManager#enroll

public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId,
                   EnrollmentCallback callback, @EnrollReason int enrollReason)

分析到这里,基本上结束,

3 指纹注册

3.1 指纹注册逻辑

在灭屏之后,PowerManagerService的Notifier线程会调用PhoneWindowManager#startedGoingToSleep通知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="
               + WindowManagerPolicyConstants.offReasonToString(why) + ")");
    }

    mGoingToSleep = true;
    mRequestedOrGoingToSleep = true;

    if (mKeyguardDelegate != null) {
        mKeyguardDelegate.onStartedGoingToSleep(why);
    }
}

调用KeyguardDelegate.onStartedGoingToSleep方法,继而又会调用KeyguardServiceWrapper.java#onStartedGoingToSleep方法,再调用KeyguardService#onStartedGoingToSleep方法;并最终到达了KeyguardViewMediator#onStartedGoingToSleep

/**
 * Called to let us know the screen was turned off.
 * @param why either {@link WindowManagerPolicyConstants#OFF_BECAUSE_OF_USER} or
 *   {@link WindowManagerPolicyConstants#OFF_BECAUSE_OF_TIMEOUT}.
 */
public void onStartedGoingToSleep(int why) {
    if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + why + ")");
    ...
    mUpdateMonitor.dispatchStartedGoingToSleep(why);
    notifyStartedGoingToSleep();
}

然后到KeyguardUpdateMonitor#dispatchStartedGoingToSleep

public void dispatchStartedGoingToSleep(int why) {
    mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0));
}

protected void handleStartedGoingToSleep(int arg1) {
    Assert.isMainThread();
    mLockIconPressed = false;
    clearBiometricRecognized();
    for (int i = 0; i < mCallbacks.size(); i++) {
        KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
        if (cb != null) {
            cb.onStartedGoingToSleep(arg1);
        }
    }
    mGoingToSleep = true;
    updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
                                  FACE_AUTH_UPDATED_GOING_TO_SLEEP);
}

private void updateBiometricListeningState(int action,
              @NonNull FaceAuthUiEvent faceAuthUiEvent) {
    updateFingerprintListeningState(action);
    updateFaceListeningState(action, faceAuthUiEvent);
}

private void updateFaceListeningState() {
    // If this message exists, we should not authenticate again until this message is
    // consumed by the handler
    if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
        return;
    }
    mHandler.removeCallbacks(mRetryFaceAuthentication);
    boolean shouldListenForFace = shouldListenForFace();
    if (mFaceRunningState == BIOMETRIC_STATE_RUNNING && !shouldListenForFace) {
        stopListeningForFace();
    } else if (mFaceRunningState != BIOMETRIC_STATE_RUNNING && shouldListenForFace) {
        startListeningForFace();
    }
}

private void updateFingerprintListeningState(int action) {
    if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
        setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
        return;
    }
    final boolean shouldListenForFingerprint =
        shouldListenForFingerprint(isUdfpsSupported());
    final boolean runningOrRestarting = 
        mFingerprintRunningState == BIOMETRIC_STATE_RUNNING
        || mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING;
    if (runningOrRestarting && !shouldListenForFingerprint) {
        if (action == BIOMETRIC_ACTION_START) {
            mLogger.v("Ignoring stopListeningForFingerprint()");
            return;
        }
        stopListeningForFingerprint();
    } else if (!runningOrRestarting && shouldListenForFingerprint) {
        if (action == BIOMETRIC_ACTION_STOP) {
            mLogger.v("Ignoring startListeningForFingerprint()");
            return;
        }
        startListeningForFingerprint();
    }
}

private void startListeningForFingerprint() {
    ....
    if (unlockPossible) {
        mFingerprintCancelSignal = new CancellationSignal();

        if (!isUnlockingWithFingerprintAllowed()) {
            mLogger.v("startListeningForFingerprint - detect");
            mFpm.detectFingerprint(
                mFingerprintCancelSignal,
                mFingerprintDetectionCallback,
                new FingerprintAuthenticateOptions.Builder()
                .setUserId(userId)
                .build());
        } else {
            mLogger.v("startListeningForFingerprint");
            mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
                              mFingerprintAuthenticationCallback,
                              null /* handler */,
                              new FingerprintAuthenticateOptions.Builder()
                              .setUserId(userId)
                              .build()
                             );
        }
        setFingerprintRunningState(BIOMETRIC_STATE_RUNNING);
    }
}

这里先创建了一个CancellationSignal对象,这个类主要是给用户提供了一个cancel的接口来取消或者监听取消操作。mFpm变量就是FingerprintManager类对象实例,会调用指纹服务注册流程。

然后调用FingerprintManager#authenticate来开始人脸解锁监听请求。

/**
 * Version of authenticate with additional options.
 * @hide
 */
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
                         @NonNull AuthenticationCallback callback, @NonNull Handler handler,
                         @NonNull FingerprintAuthenticateOptions options) {
    if (mService != null) {
        try {
            useHandler(handler);
            mAuthenticationCallback = callback;
            mCryptoObject = crypto;
            final long operationId = crypto != null ? crypto.getOpId() : 0;
            final long authId = mService.authenticate(
                mToken, operationId, mServiceReceiver, options);
            if (cancel != null) {
                cancel.setOnCancelListener(
                    new OnAuthenticationCancelListener(authId));
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception while authenticating: ", e);
            // 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(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
                                                          0 /* vendorCode */));
        }
    }
}

然后调用FingerprintService#authenticate

@Override // Binder call
public void authenticate(final IBinder token,
                final long operationId,
                final IFingerprintServiceReceiver receiver,
                final FingerprintAuthenticateOptions options) {
    final int callingUid = Binder.getCallingUid();
    final int callingPid = Binder.getCallingPid();
    final int callingUserId = UserHandle.getCallingUserId();
    final String opPackageName = options.getOpPackageName();
    final String attributionTag = options.getAttributionTag();
    final int userId = options.getUserId();

    if (!canUseFingerprint(
        opPackageName,
        attributionTag,
        true /* requireForeground */,
        callingUid,
        callingPid,
        callingUserId)) {
        Slog.w(TAG, "Authenticate rejecting package: " + opPackageName);
        return -1;
    }

    // Keyguard check must be done on the caller's binder identity, 
    // since it also checks permission.
    final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);

    // Clear calling identity when checking LockPatternUtils for StrongAuth flags.
    final long identity1 = Binder.clearCallingIdentity();
    try {
      if (isKeyguard && Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
            // If this happens, something in KeyguardUpdateMonitor is wrong.
            // SafetyNet for b/79776455
            EventLog.writeEvent(0x534e4554, "79776455");
            Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown");
            return -1;
        }
    } finally {
        Binder.restoreCallingIdentity(identity1);
    }

    final boolean restricted =getContext().checkCallingPermission(MANAGE_FINGERPRINT)
        != PackageManager.PERMISSION_GRANTED;
    final int statsClient = isKeyguard ? BiometricsProtoEnums.CLIENT_KEYGUARD
        : BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;

    final Pair<Integer, ServiceProvider> provider;
    if (options.getSensorId() == FingerprintManager.SENSOR_ID_ANY) {
        provider = mRegistry.getSingleProvider();
    } else {
        Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
        provider = new Pair<>(options.getSensorId(),
                              mRegistry.getProviderForSensor(options.getSensorId()));
    }

    if (provider == null) {
        Slog.w(TAG, "Null provider for authenticate");
        return -1;
    }
    options.setSensorId(provider.first);

    final FingerprintSensorPropertiesInternal sensorProps =
        provider.second.getSensorProperties(options.getSensorId());
    if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
        && sensorProps != null && (sensorProps.isAnyUdfpsType()
                                   || sensorProps.isAnySidefpsType())) {
        try {
            return authenticateWithPrompt(operationId, sensorProps, callingUid,
                                          callingUserId, receiver, opPackageName,
                                          options.isIgnoreEnrollmentState());
        } catch (PackageManager.NameNotFoundException e) {
            Slog.e(TAG, "Invalid package", e);
            return -1;
        }
    }
    final long identity2 = Binder.clearCallingIdentity();
    try {
        VirtualDeviceManagerInternal vdm = getLocalService(
            VirtualDeviceManagerInternal.class);
        if (vdm != null) {
            vdm.onAuthenticationPrompt(callingUid);
        }
    } finally {
        Binder.restoreCallingIdentity(identity2);
    }
    return provider.second.scheduleAuthenticate(token, operationId, 0 /* cookie */,
                   new ClientMonitorCallbackConverter(receiver), options,
                                    restricted, statsClient, isKeyguard);
}

这里首先调用canUseFingerprint进行权限校验,这个跟face是一样的,这里就不看了。

接着判断如果不是锁屏界面,就判断是不是生物认证,如果是生物认证就调用authenticateWithPrompt,否则就调动provider.second.scheduleAuthenticate。

这里我们看provider.second.scheduleAuthenticate,provider.second.scheduleAuthenticate在前面的时候介绍过,其实就是调用ServiceProvider#scheduleAuthenticate,而Fingerprint21实现了ServiceProvider。

public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider

因此,我们直接看Fingerprint21#scheduleAuthenticate

@Override
public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
               int cookie, @NonNull ClientMonitorCallbackConverter listener,
               @NonNull FingerprintAuthenticateOptions options,
               long requestId, boolean restricted, int statsClient,
               boolean allowBackgroundAuthentication) {
    mHandler.post(() -> {
        scheduleUpdateActiveUserWithoutHandler(options.getUserId());

        final boolean isStrongBiometric = 
            Utils.isStrongBiometric(mSensorProperties.sensorId);
        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));
        mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
    });
}

这里说明一下,mScheduler是在这里定义的

@NonNull
private List<ServiceProvider> getHidlProviders(
    @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
    final List<ServiceProvider> providers = new ArrayList<>();

    for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) {
        final Fingerprint21 fingerprint21;
        ...
        } else {
            fingerprint21 = Fingerprint21.newInstance(getContext(),
                    mBiometricStateCallback, hidlSensor, mHandler,
                    mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
        }
        providers.add(fingerprint21);
    }

    return providers;
}

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

继续往下看,类BiometricScheduler的scheduleClientMonitor

/**
 * Adds a {@link BaseClientMonitor} to the pending queue
 *
 * @param clientMonitor        operation to be scheduled
 * @param clientCallback optional callback, invoked when the client state changes.
 */
public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
                                  @Nullable ClientMonitorCallback clientCallback) {
    // If the incoming operation should interrupt preceding clients, 
    // mark any interruptable pending clients as canceling. 
    // Once they reach the head of the queue, 
    // the scheduler will send ERROR_CANCELED and skip the operation.
    if (clientMonitor.interruptsPrecedingClients()) {
        for (BiometricSchedulerOperation operation : mPendingOperations) {
            if (operation.markCanceling()) {
                Slog.d(getTag(), "New client, marking pending op as canceling: " 
                       + operation);
            }
        }
    }

    mPendingOperations.add(
        new BiometricSchedulerOperation(clientMonitor, clientCallback));
    Slog.d(getTag(), "[Added] " + clientMonitor
           + ", new queue size: " + mPendingOperations.size());

    // If the new operation should interrupt preceding clients, 
    // and if the current operation is cancellable, start the cancellation process.
    if (clientMonitor.interruptsPrecedingClients()
        && mCurrentOperation != null
        && mCurrentOperation.isInterruptable()
        && mCurrentOperation.isStarted()) {
        Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
        mCurrentOperation.cancel(mHandler, mInternalCallback);
    } else {
        startNextOperationIfIdle();
    }
}

然后来到方法startNextOperationIfIdle

protected void startNextOperationIfIdle() {
    ...
    mCurrentOperation = mPendingOperations.poll();
    Slog.d(getTag(), "[Polled] " + mCurrentOperation);
    ...
    if (mGestureAvailabilityDispatcher != null 
        && mCurrentOperation.isAcquisitionOperation()) {
            mGestureAvailabilityDispatcher.markSensorActive(
                    mCurrentOperation.getSensorId(), true /* active */);
    }
    
    // Not all operations start immediately. BiometricPrompt waits for its operation
    // to arrive at the head of the queue, before pinging it to start.
    final int cookie = mCurrentOperation.isReadyToStart(mInternalCallback);
    if (cookie == 0) {
        if (!mCurrentOperation.start(mInternalCallback)) {
            // Note down current length of queue
            final int pendingOperationsLength = mPendingOperations.size();
            final BiometricSchedulerOperation lastOperation = 
                mPendingOperations.peekLast();
            Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
                   + ". Last pending operation: " + lastOperation);

            // Then for each operation currently in the pending queue 
            // at the time of this failure, do the same as above. Otherwise, 
            // it's possible that something like setActiveUser fails,
            // but then authenticate (for the wrong user) is invoked.
            for (int i = 0; i < pendingOperationsLength; i++) {
                final BiometricSchedulerOperation operation = 
                    mPendingOperations.pollFirst();
                if (operation != null) {
                    Slog.w(getTag(), "[Aborting Operation] " + operation);
                    operation.abort();
                } else {
                    Slog.e(getTag(), "Null operation, index: " + i
                           + ", expected length: " + pendingOperationsLength);
                }
            }

            // It's possible that during cleanup a new set of operations came in.
            // We can try to run these. A single request from the manager layer 
            // to the service layer may actually be multiple operations 
            // (i.e. updateActiveUser + authenticate).
            mCurrentOperation = null;
            startNextOperationIfIdle();
        }
    } else {
        try {
            mBiometricService.onReadyForAuthentication(
                mCurrentOperation.getClientMonitor().getRequestId(), cookie);
        } catch (RemoteException e) {
            Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
        }
        Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
    }
}

mCurrentOperation.start(mInternalCallback),这里要分析变量currentClient,它是从前面startNextOperationIfIdle拿到的。

mCurrentOperation = mPendingOperations.poll();

而又是从前面BiometricScheduler#scheduleClientMonitor从添加的

mPendingOperations.add(new BiometricSchedulerOperation(clientMonitor, clientCallback));
Slog.d(getTag(), "[Added] " + clientMonitor
                + ", new queue size: " + mPendingOperations.size());

这里是创建了一个BiometricSchedulerOperation对象,来保存clientMonitor

BiometricSchedulerOperation(@NonNull BaseClientMonitor clientMonitor,
                            @Nullable ClientMonitorCallback callback) {
    this(clientMonitor, callback, STATE_WAITING_IN_QUEUE);
}

因此上面的mCurrentOperation.start实际上是调用的BiometricSchedulerOperation的start。

/**
 * Start this operation without waiting for a cookie
 * (i.e. {@link #isReadyToStart(ClientMonitorCallback)}  returns zero}
 *
 * @param callback lifecycle callback
 * @return if this operation started
 */
public boolean start(@NonNull ClientMonitorCallback callback) {
    if (errorWhenNoneOf("start",
                        STATE_WAITING_IN_QUEUE,
                        STATE_WAITING_FOR_COOKIE,
                        STATE_WAITING_IN_QUEUE_CANCELING)) {
        return false;
    }

    if (mClientMonitor.getCookie() != 0) {
        String err = "operation requires cookie";
        if (mIsDebuggable.getAsBoolean()) {
            throw new IllegalStateException(err);
        }
        Slog.e(TAG, err);
    }

    return doStart(callback);
}

private boolean doStart(@NonNull ClientMonitorCallback callback) {
    mOnStartCallback = callback;
    final ClientMonitorCallback cb = getWrappedCallback(callback);

    if (mState == STATE_WAITING_IN_QUEUE_CANCELING) {
        Slog.d(TAG, "Operation marked for cancellation, cancelling now: " + this);

        cb.onClientFinished(mClientMonitor, true /* success */);
        if (mClientMonitor instanceof ErrorConsumer) {
            final ErrorConsumer errorConsumer = (ErrorConsumer) mClientMonitor;
            errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
                                  0 /* vendorCode */);
        } else {
            Slog.w(TAG, "monitor cancelled but does not implement ErrorConsumer");
        }

        return false;
    }

    if (isUnstartableHalOperation()) {
        Slog.v(TAG, "unable to start: " + this);
        ((HalClientMonitor<?>) mClientMonitor).unableToStart();
        cb.onClientFinished(mClientMonitor, false /* success */);
        return false;
    }

    mState = STATE_STARTED;
    mClientMonitor.start(cb);

    Slog.v(TAG, "started: " + this);
    return true;
}

最后还是调用了mClientMonitor.start(cb);,这个mClientMonitor正是从BiometricSchedulerOperation的构造函数赋值的。而mClientMonitor我们知道,它是在前面Fingerprint21#scheduleAuthenticate中创建的。

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));
mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);

以前,我们直接看FingerprintAuthenticationClient的start方法。

@Override
public void start(@NonNull ClientMonitorCallback callback) {
    super.start(callback);

    if (mSensorProps.isAnyUdfpsType()) {
        // UDFPS requires user to touch before becoming "active"
        mState = STATE_STARTED_PAUSED;
    } else {
        mState = STATE_STARTED;
    }
}

这里只是赋值状态为STATE_STARTED,我们直接看父类的super.start,这里是AuthenticationClient 类下的start方法。

/**
 * Start authentication
 */
@Override
public void start(@NonNull ClientMonitorCallback callback) {
    super.start(callback);

    final @LockoutTracker.LockoutMode int lockoutMode;
    if (mShouldUseLockoutTracker) {
        lockoutMode = mLockoutTracker.getLockoutModeForUser(getTargetUserId());
    } else {
        lockoutMode = getBiometricContext().getAuthSessionCoordinator()
            .getLockoutStateFor(getTargetUserId(), mSensorStrength);
    }

    if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
        Slog.v(TAG, "In lockout mode(" + lockoutMode 
               + ") ; disallowing authentication");
        int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
            ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
            : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
        onError(errorCode, 0 /* vendorCode */);
        return;
    }

    if (mTaskStackListener != null) {
        mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
    }

    Slog.d(TAG, "Requesting auth for " + getOwnerString());

    mStartTimeMs = System.currentTimeMillis();
    mAuthAttempted = true;
    startHalOperation();
}

很明显,这里是startHalOperation(),实际上就是调用到FingerprintAuthenticationClient 类下的startHalOperation。

@Override
protected void startHalOperation() {

    if (mSensorPrivacyManager != null
        && mSensorPrivacyManager
        .isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE,
                                SensorPrivacyManager.Sensors.CAMERA)) {
        onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
        mCallback.onClientFinished(this, false /* success */);
        return;
    }

    try {
        getFreshDaemon().authenticate(mOperationId);
    } catch (RemoteException e) {
        Slog.e(TAG, "Remote exception when requesting auth", e);
        onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
        mCallback.onClientFinished(this, false /* success */);
    }
}

getFreshDaemon().authenticate 就是进行指纹服务注册,后面会继续分析相关底层。

 @VisibleForTesting
synchronized IBiometricsFingerprint getDaemon() {
    if (mTestHalEnabled) {
        final TestHal testHal = new TestHal(mContext, mSensorId);
        testHal.setNotify(mHalResultController);
        return testHal;
    }

    if (mDaemon != null) {
        return mDaemon;
    }

    Slog.d(TAG, "Daemon was null, reconnecting, current operation: "
           + mScheduler.getCurrentClient());
    try {
        mDaemon = IBiometricsFingerprint.getService();
    } catch (java.util.NoSuchElementException e) {
        // Service doesn't exist or cannot be opened.
        Slog.w(TAG, "NoSuchElementException", e);
    } catch (RemoteException e) {
        Slog.e(TAG, "Failed to get fingerprint HAL", e);
    }

    if (mDaemon == null) {
        Slog.w(TAG, "Fingerprint HAL not available");
        return null;
    }

    mDaemon.asBinder().linkToDeath(this, 0 /* flags */);

    // 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;
    }

    Slog.d(TAG, "Fingerprint HAL ready, HAL ID: " + halId);
    if (halId != 0) {
        scheduleLoadAuthenticatorIds();
        scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */);
    } else {
        Slog.e(TAG, "Unable to set callback");
        mDaemon = null;
    }

    return mDaemon;
}

mDaemon 是通过mDaemon = IBiometricsFingerprint.getService();拿到的,前面说过,它是跨进程调用远程对象BiometricsFingerprint.cpp。

我们来看BiometricsFingerprint

//hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId,
        uint32_t gid) {
    return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid));
}

这里mDevice是在BiometricsFingerprint构造里面初始化的。

BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr), mDevice(nullptr) {
    sInstance = this; // keep track of the most recent instance
    mDevice = openHal();
    if (!mDevice) {
        ALOGE("Can't open HAL module");
    }
}

再来看openHal方法

fingerprint_device_t* BiometricsFingerprint::openHal() {
    int err;
    const hw_module_t *hw_mdl = nullptr;
    ALOGD("Opening fingerprint hal library...");
    if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) {
        ALOGE("Can't open fingerprint HW Module, error: %d", err);
        return nullptr;
    }

    if (hw_mdl == nullptr) {
        ALOGE("No valid fingerprint module");
        return nullptr;
    }

    fingerprint_module_t const *module =
        reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
    if (module->common.methods->open == nullptr) {
        ALOGE("No valid open method");
        return nullptr;
    }

    hw_device_t *device = nullptr;

    if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) {
        ALOGE("Can't open fingerprint methods, error: %d", err);
        return nullptr;
    }

    if (kVersion != device->version) {
        // enforce version on new devices because of HIDL@2.1 translation layer
        ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
        return nullptr;
    }

    fingerprint_device_t* fp_device =
        reinterpret_cast<fingerprint_device_t*>(device);

    if (0 != (err =
            fp_device->set_notify(fp_device, BiometricsFingerprint::notify))) {
        ALOGE("Can't register fingerprint module callback, error: %d", err);
        return nullptr;
    }

    return fp_device;
}

这个方法最终会访问到底层了,比如我们熟悉的hw_get_module。设置回调到底软 ,后面有设置

dev->set_notify = set_notify_callback;

我们来看module->common.methods->open

这个open方法主要是将厂商指纹模组模块的算法识别逻辑结果和HAL层进行绑定(一般是fingerprint.default.so文件),设置回调通知,这个文件一般都不开源,不过Android原生也是有这部分代码的(当然只是看看,并不能使用)

我们来看hardware/libhardware/modules/fingerprint/fingerprint.c

static int fingerprint_open(const hw_module_t* module, const char __unused *id,
                            hw_device_t** device)
{
    if (device == NULL) {
        ALOGE("NULL device on open");
        return -EINVAL;
    }

    fingerprint_device_t *dev = malloc(sizeof(fingerprint_device_t));
    memset(dev, 0, sizeof(fingerprint_device_t));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;
    dev->common.module = (struct hw_module_t*) module;
    dev->common.close = fingerprint_close;

    dev->pre_enroll = fingerprint_pre_enroll;
    dev->enroll = fingerprint_enroll;
    dev->get_authenticator_id = fingerprint_get_auth_id;
    dev->cancel = fingerprint_cancel;
    dev->remove = fingerprint_remove;
    dev->set_active_group = fingerprint_set_active_group;
    dev->authenticate = fingerprint_authenticate;
    dev->set_notify = set_notify_callback;
    dev->notify = NULL;

    *device = (hw_device_t*) dev;
    return 0;
}

static struct hw_module_methods_t fingerprint_module_methods = {
    .open = fingerprint_open,
};

fingerprint_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag                = HARDWARE_MODULE_TAG,
        .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
        .hal_api_version    = HARDWARE_HAL_API_VERSION,
        .id                 = FINGERPRINT_HARDWARE_MODULE_ID,
        .name               = "Demo Fingerprint HAL",
        .author             = "The Android Open Source Project",
        .methods            = &fingerprint_module_methods,
    },
};

好了,后面authenticate的逻辑,我们没有代码就不分析了,指纹服务注册分析到此为止。

3.2 总结在这里插入图片描述

4 指纹解锁

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

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

  • 23
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值