Android fingerprint startup process

Preface: I have summarized the Android fingerprint debugging process before https://blog.csdn.net/weixin_41486477/article/details/108592205  . This chapter mainly organizes the Android fingerprint startup process, focusing on the hal and framework parts.

1. Look at the fingerprint startup process from the Android system startup process

Source of the picture below  

The first stage: Boot ROM, after the Android device is powered on, it will first execute from the boot code of the on-chip ROM of the processor. The on-chip ROM will look for the Bootloader code and load it into the memory.

                  The main thing is to power on and start the system.

The second stage: Bootloader starts to execute, first is responsible for completing the initialization of the hardware, and then finds the Linux kernel code and loads it into the memory.

                  During the boot process, the bootloader (bootable/bootloader/lk by default) will select the appropriate devicetree (dts) to load into the memory according to the machine hardware information. If the pin id is compatible, then the value of the ID pin can be read ( This is pulled by the hardware, just confirm with the hardware engineer how it corresponds to the IC) The IC for the fingerprint is judged.

The third stage: Kernel, the Linux kernel starts, initializes various hardware and software environments, loads drivers, mounts the root file system, looks for the init.rc file in the system files, and starts the init process.

                  In Kernel, load the fingerprint driver, create a device node based on the incoming dts information, and register the device.

The fourth stage: Init, initialize and start the property service, and start the Zygote process.

                  Find [email protected], start [email protected], go to open fingerprint.deault.so, and wait for communication with the upper layer.

The fifth stage: the Zygote process is started, the java virtual machine is created and the JNI method is registered for the java virtual machine, the server-side Socket is created, and the SystemServer process is started.

The sixth stage: The SystemServer process starts, starts the Binder thread pool and SystemServiceManager, and starts various system services.

                 Will start Fingerprintservice

 The above is the start-up process of each stage of the fingerprint from the Android start-up process, which will be introduced in detail below.

2. Drive layer     

The main thing is the registration of the device node driver. I won't go into details here, and focus on the probe function.

Three.hal layer

First, hardware/interfaces/biometrics/fingerprint/2.1/default/[email protected] (hereinafter referred to as 2.1 rc)

service vendor.fps_hal /vendor/bin/hw/[email protected]
    # "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
    writepid /dev/cpuset/system-background/tasks

It will make [email protected] (hereinafter referred to as 2.1 bin) located in the system vendor/bin/hw to start automatically after booting, and will register 2.1 service after booting

The code corresponding to the bin service is in hardware/interfaces/biometrics/fingerprint/2.1/default/service.cpp. The entire registration process has only two steps. First, the incoming IBiometricsFingerprint interface object is instantiated, and then the service is registered to hwservicemanager through registerAsService.

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
}

hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp, focusing on the openHal function, will open fingerprint.default.so

fingerprint_device_t* BiometricsFingerprint::openHal() {
    int err;
    const hw_module_t *hw_mdl = nullptr;
    ALOGD("Opening fingerprint hal library...");
    //*******打开fingerprint.default.so********
    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 [email protected] 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;
}

About fingerprint.default.so this is provided by the supplier, generally not open source, but Android native also has this part of the code (of course, just take a look, and can’t use it)

hardware/libhardware/include/hardware/fingerprint.h

hardware/libhardware/modules/fingerprint/fingerprint.c

This part of the code is no longer expanded and pasted here, you can go and see it yourself, mainly fingerprint_open opens the device (device node), and then defines a series of functions.

    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;

Four.framework layer

First, after the SystemServer is started, it will determine whether the device supports fingerprints, if there is a start FingerprintService

frameworks/base/services/java/com/android/server/SystemServer.java

        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
                traceBeginAndSlog("StartFingerprintSensor");
                mSystemServiceManager.startService(FingerprintService.class);
                traceEnd();
            }

The judgment of mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) here, you can go to frameworks/base/core/java/android/content/pm/PackageManager.java to follow the code to see, the logic is very simple.

Is to determine whether there is an android.hardware.fingerprint.xml file in the vendor/etc/permissions directory in the system

The debugging article said that this configuration is the key to whether there is a fingerprint option in the setting:

PRODUCT_COPY_FILES := frameworks/native/data/etc/android.hardware.fingerprint.xml:vendor/etc/permissions/android.hardware.fingerprint.xml 

Next, go to frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java, the first half of the code below is the part that communicates with the hal 2.1 service, through mDaemon = IBiometricsFingerprint.getService(), get 2.1 service

In the second half, it can be seen that it inherits IFingerprintService.aidl. This aidl class is the bridge that realizes the communication between Manager and Service.

 public synchronized IBiometricsFingerprint getFingerprintDaemon() {
        if (mDaemon == null) {
            Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
            try {
                mDaemon = IBiometricsFingerprint.getService();
            } catch (java.util.NoSuchElementException e) {
                // Service doesn't exist or cannot be opened. Logged below.
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to get biometric interface", e);
            }
            if (mDaemon == null) {
                Slog.w(TAG, "fingerprint HIDL not available");
                return null;
            }

            mDaemon.asBinder().linkToDeath(this, 0);

            try {
                mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to open fingerprint HAL", e);
                mDaemon = null; // try again later!
            }

            if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
            if (mHalDeviceId != 0) {
                loadAuthenticatorIds();
                updateActiveGroup(ActivityManager.getCurrentUser(), null);
                doFingerprintCleanupForUser(ActivityManager.getCurrentUser());
            } else {
                Slog.w(TAG, "Failed to open Fingerprint HAL!");
                MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
                mDaemon = null;
            }





//************************************************************************************//



 private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
        @Override // Binder call
        public long preEnroll(IBinder token) {
            checkPermission(MANAGE_FINGERPRINT);
            return startPreEnroll(token);
        }

        @Override // Binder call
        public int postEnroll(IBinder token) {
            checkPermission(MANAGE_FINGERPRINT);
            return startPostEnroll(token);
        }

        @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 int limit = mContext.getResources().getInteger(
                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);

            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
            if (enrolled >= limit) {
                Slog.w(TAG, "Too many fingerprints registered");
                return;
            }
        }
        return mDaemon;
    }

The encapsulation of FingerprintService to the next level is FingerprintManager, and the application app can communicate with it directly

frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java (The following is the code for searching mService, you can go and see by yourself)

    private IFingerprintService mService;
        if (mService != null) try {
            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,

        if (mService != null) {
                mService.authenticate(mToken, sessionId, userId, mServiceReceiver,
               
        if (mService != null) try {
            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
            
        if (mService != null) try {
            result = mService.preEnroll(mToken);
        if (mService != null) try {
            result = mService.postEnroll(mToken);
        if (mService != null) try {
            mService.setActiveUser(userId);
        if (mService != null) try {
            mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
            mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
        if (mService != null) try {
            mService.enumerate(mToken, userId, mServiceReceiver);
            
        if (mService != null) {
                mService.rename(fpId, userId, newName);
        if (mService != null) try {
            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
        if (mService != null) try {
            return mService.hasEnrolledFingerprints(
        if (mService != null) try {
            return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
        if (mService != null) {
                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
        if (mService != null) {
                return mService.getAuthenticatorId(mContext.getOpPackageName());
        if (mService != null) {
                mService.resetTimeout(token);
        if (mService == null) {
        if (mService != null) try {
            mService.cancelEnrollment(mToken);
        if (mService != null) try {
            mService.cancelAuthentication(mToken, mContext.getOpPackageName());

In the above code, you can find that the FingerprintManager does not actually implement any interface. It is the IFingerprintService that is called. Here is the aidl. The FingerprintManager obtains the Fingerprintservice through the Stub of the aidl, and then calls the service method here to operate the service. This is the role of aidl.

frameworks/base/core/java/android/hardware/fingerprint/IFingerprintService.aidl (If you look at the complete code, the interface here is exactly the same as that called in FingerprintManager)


interface IFingerprintService {
    // Authenticate the given sessionId with a fingerprint
    void authenticate(IBinder token, long sessionId, int userId,
            IFingerprintServiceReceiver receiver, int flags, String opPackageName,
            in Bundle bundle, IBiometricPromptReceiver dialogReceiver);

    // Cancel authentication for the given sessionId
    void cancelAuthentication(IBinder token, String opPackageName);

    // Start fingerprint enrollment
    void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver,
            int flags, String opPackageName);

    // Cancel enrollment in progress
    void cancelEnrollment(IBinder token);

    // Any errors resulting from this call will be returned to the listener
    void remove(IBinder token, int fingerId, int groupId, int userId,
            IFingerprintServiceReceiver receiver);

    // Rename the fingerprint specified by fingerId and groupId to the given name
    void rename(int fingerId, int groupId, String name);

    // Get a list of enrolled fingerprints in the given group.
    List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName);

    // Determine if HAL is loaded and ready
    boolean isHardwareDetected(long deviceId, String opPackageName);

    // Get a pre-enrollment authentication token
    long preEnroll(IBinder token);

    // Finish an enrollment sequence and invalidate the authentication token
    int postEnroll(IBinder token);

   

V. Summary

Based on the above, such a flow chart can be drawn (the following takes Goodix fingerprint as an example, the process is the same)

System APP issued registration command -> FingerprintManager received command -> FingerprintService received command -> (2.1 service) BiometricsFingerprint received command -> (fingerprint.default.so) Fingerprint.cpp received command -> Fingerprint CA received command ->Fingerprint TA receives command ->SPI data collection\algorithm for registration, etc.

Guess you like

Origin blog.csdn.net/weixin_41486477/article/details/112863054