Android 指紋啓動流程

前言:之前總結過Android指紋調試流程https://blog.csdn.net/weixin_41486477/article/details/108592205 ,本章主要整理Android 指紋啓動流程,側重於hal和framework部分。

一.從Android系統啓動流程看指紋啓動流程

下圖圖片出處  

第一階段:Boot ROM,Android設備上電後,首先會從處理器片上ROM的啓動引導代碼開始執行,片上ROM會尋找Bootloader代碼,並加載到內存。

                  主要就是上電讓系統啓動。

第二階段:Bootloader開始執行,首先負責完成硬件的初始化,然後找到Linux內核代碼,並加載到內存。

                  啓動過程中,bootloader(默認是bootable/bootloader/lk)會根據機器硬件信息選擇合適的devicetree(dts)裝入內存,如果採用pin id兼容,那麼在此時就可以通過讀取ID pin的值(這個是硬件拉的,跟硬件工程師確認是怎麼對應IC的即可)判斷指紋的IC了。

第三階段:Kernel,Linux內核開始啓動,初始化各種軟硬件環境,加載驅動程序,掛載根文件系統,在系統文件中尋找init.rc文件,並啓動init進程。

                  Kernel中,加載指紋驅動,根據傳入的dts信息創建設備節點,註冊設備。

第四階段:Init,初始化和啓動屬性服務,並且啓動Zygote進程。

                  找到[email protected],啓動[email protected],會去open  fingerprint.deault.so,等待與上層通信。

第五階段:Zygote進程啓動,創建java虛擬機併爲java虛擬機註冊JNI方法,創建服務器端Socket,啓動SystemServer進程。

第六階段:SystemServer進程啓動,啓動Binder線程池和SystemServiceManager,並且啓動各種系統服務。

                 會啓動Fingerprintservice

 以上是從Android啓動流程看每個階段指紋的啓動流程 ,下面依次詳細展開介紹。

二.驅動層     

主要就是設備節點驅動的註冊,在此不再詳細說了,重點關注probe函數。

三.hal層

首先,hardware/interfaces/biometrics/fingerprint/2.1/default/[email protected](以下簡稱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

會使位於系統vendor/bin/hw下的[email protected](以下簡稱2.1 bin)開機自啓動,啓動後會註冊2.1 service

該bin服務對應的代碼在:hardware/interfaces/biometrics/fingerprint/2.1/default/service.cpp,整個註冊過程只有兩步,首先實例化傳入的 IBiometricsFingerprint 接口對象,然後通過 registerAsService 將服務註冊到 hwservicemanager。

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,重點關注openHal函數,會去打開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;
}

關於fingerprint.default.so這個都是供應商提供的,一般都不開源,不過Android原生也是有這部分代碼的(當然只是看看,並不能使用)

hardware/libhardware/include/hardware/fingerprint.h

hardware/libhardware/modules/fingerprint/fingerprint.c

這部分代碼不再展開貼在這裏了,大家可以自行去看看,主要就是fingerprint_open打開設備(設備節點),然後定義了一系列函數。

    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;

四.framework層

首先是SystemServer啓動後,會去判斷設備是否支持指紋,如果有start  FingerprintService

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

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

此處mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)的判斷,大家可以去frameworks/base/core/java/android/content/pm/PackageManager.java中追代碼看看,邏輯很簡單。

就是判斷系統內vendor/etc/permissions目錄下是否有:android.hardware.fingerprint.xml 文件

調試的那篇說過這個配置是setting裏有沒有指紋選項的關鍵:

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

下面轉到,frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java,以下代碼前半部分是與hal 2.1 service通信的部分,通過mDaemon = IBiometricsFingerprint.getService(),獲取2.1 service

後半部分可以看出其繼承IFingerprintService.aidl,這個aidl類就是實現Manager和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;
    }

對FingerprintService再往上一層的封裝是FingerprintManager,應用app可以直接和它通信

frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java  (以下爲搜索mService的代碼,大家可以自己去看看)

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

以上代碼大家可以發現FingerprintManager其實並沒有真正實現什麼接口,都是調用的IFingerprintService,這裏就用到aidl了,FingerprintManager通過aidl的Stub獲取了Fingerprintservice,然後在這裏去調用這個service的方法,以操作service,這就是aidl的作用。

frameworks/base/core/java/android/hardware/fingerprint/IFingerprintService.aidl (大家如果去看完整的代碼,這裏的接口是和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);

   

五.總結

根據以上可以畫出這樣一張流程圖(以下以匯頂指紋爲例,流程上都是一樣的)

System APP下發註冊命令->FingerprintManager收到命令->FingerprintService收到命令->(2.1 service)BiometricsFingerprint收到命令->(fingerprint.default.so)Fingerprint.cpp收到命令->指紋CA收到命令->指紋TA收到命令->SPI採集數據\算法進行註冊等

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章