全面解析Android系统指纹启动流程

本章主要整理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进程。

找到android.hardware.biometrics.fingerprint@2.1-service.rc,启动android.hardware.biometrics.fingerprint@2.1-service,会去open  fingerprint.deault.so,等待与上层通信。

第五阶段

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

第六阶段

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

以上是从Android启动流程看每个阶段指纹的启动流程 ,下面依次详细展开介绍。

二.驱动层     

主要就是设备节点驱动的注册,在此不再详细说了,重点关注probe函数。

三.hal层

首先,hardware/interfaces/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc(以下简称2.1 rc)

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
    writepid /dev/cpuset/system-background/tasks

会使位于系统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,整个注册过程只有两步,首先实例化传入的 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 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;
}

关于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采集数据\算法进行注册等

以上就是全面解析Android系统指纹启动流程的详细内容,更多关于Android启动流程的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android添加指纹解锁功能的实现代码

    前言 指纹解锁技术成为当前验证用户信息的重要手段,基本上当前手机都配置了指纹解锁.当开发的APP需要加密验证时可以考虑添加系统指纹解锁功能. 添加指纹解锁功能步骤很简单,大致过程如下: 1 添加权限 在Manifest.xml文件中添加访问用户指纹的权限. <uses-permission android:name="android.permission.USE_FINGERPRINT"/> 2 声明系统提供的指纹管理类对象 private FingerprintManag

  • Android指纹登录工具类封装

    本文实例为大家分享了Android指纹登录工具类的封装代码,供大家参考,具体内容如下 核心 Android 指纹 是在 6.0 才出来的一个重要的功能 @RequiresApi(api = Build.VERSION_CODES.M) 核心的两个 api: FingerprintManager KeyguardManager step1 判断android 版本,如果小于 6.0 支持不了指纹 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M){

  • Android指纹识别功能

    指纹识别作为最新兴起的用户身份验证机制,已经被越来越多的应用程序所采用,相比传统的密码九宫格等验证方法,指纹识别更加安全,如今越来越多的安卓手机配备了指纹识别模块,我们就来尝试一下这一项新兴的技术 首先创建一个安卓项目,指纹识别作为最近几年才兴起的技术,对安卓api level要求较高(api 23以上即jdk6.0以上) 创建一个button用于触发指纹识别,并在MainActivity里对其监听,代码如下 Button button=(Button)findViewById(R.id.che

  • Android指纹识别API讲解,一种更快更好的用户体验

    我发现了一个比较怪的现象.在iPhone上使用十分普遍的指纹认证功能,在Android手机上却鲜有APP使用,我简单观察了一下,发现Android手机上基本上只有支付宝.微信和极少APP支持指纹认证功能,就连银行和金融类的应用都基本不支持,甚至很多开发者都不知道Android系统是有指纹认证的官方API的. 事实上,Android从6.0系统开始就支持指纹认证功能了,但是指纹功能还需要有硬件支持才行,而Android手机的硬件都是由各厂商生产的,手机档次也参差不齐,因此不能像iPhone那样保证

  • Android指纹识别认识和基本使用详解

    本文为大家分享了Android指纹识别认识和基本使用方法,供大家参考,具体内容如下 1.其实现在写指纹的博客已经有很多了,但是很多情况下,很多写的有点多,对需要快速上手和使用的人来说,没耐性去看那么多原理,源码之类的东西.大部分人都是直接复制,修改. 2.楼主表示一开始也是直接看人家代码,截一段一段的,很醉,而且下载demo还要c币啊.所以还是自己记录一下吧.也方便大家复制.哈哈. 3.首先来看一下模仿下支付宝的效果. 4.基本识别功能可以完成,至于每个人需求不一样,所以只是演示,由于本人手机最

  • android实现指纹识别功能

    功能介绍 支持指纹识别,兼容 Android 6.0 和 Android 9.0 提供界面友好的指纹识别弹窗,可自定义其样式 实现国际化(支持中文和英文) Gradle依赖 dependencies { implementation 'com.github.ZuoHailong:BiometricPrompt:0.2.3' } 指纹识别用法简述 FingerprintVerifyManager.Builder builder = new FingerprintVerifyManager.Buil

  • 浅谈Android 指纹解锁技术

    什么是指纹解锁技术 根据人的指纹来验证是否能够解锁的技术,类似于通过输入密码来解锁,都是通过一定的数字特征来解锁. 指纹解锁技术原理理解 首先说明每个人的每个指纹信息都是独一无二的,皮肤纹路在图案,断点,交叉点上各不相同,通过光学感应读出指纹的图片信息也是独一无二的. 先保存一个人的指纹特征(图片信息根据算法生成的数据),然后再使用时利用这个人的这个指纹特征去和先前保存的指纹特征做对比,对比一致则解锁成功,对比不一致则解锁失败,对比结果并不是100%一样,而可以按照一个比例来判定,比如90%一样

  • 全面解析Android系统指纹启动流程

    本章主要整理Android 指纹启动流程,侧重于hal和framework部分. 一.从Android系统启动流程看指纹启动流程 下图图片出处  → 第一阶段 Boot ROM,Android设备上电后,首先会从处理器片上ROM的启动引导代码开始执行,片上ROM会寻找Bootloader代码,并加载到内存.主要就是上电让系统启动. 第二阶段 Bootloader开始执行,首先负责完成硬件的初始化,然后找到Linux内核代码,并加载到内存. 启动过程中,bootloader(默认是bootable

  • Android okhttp的启动流程及源码解析

    前言 这篇文章主要讲解了okhttp的主要工作流程以及源码的解析. 什么是OKhttp 简单来说 OkHttp 就是一个客户端用来发送 HTTP 消息并对服务器的响应做出处理的应用层框架. 那么它有什么优点呢? 易使用.易扩展. 支持 HTTP/2 协议,允许对同一主机的所有请求共用同一个 socket 连接. 如果 HTTP/2 不可用, 使用连接池复用减少请求延迟. 支持 GZIP,减小了下载大小. 支持缓存处理,可以避免重复请求. 如果你的服务有多个 IP 地址,当第一次连接失败,OkHt

  • 详解Android Activity的启动流程

    前言 activity启动的流程分为两部分:一是在activity中通过startActivity(Intent intent)方法启动一个Activity:二是我们在桌面通过点击应用图标启动一个App然后显示Activity:第二种方式相较于第一种方式更加全面,所以本文会以第二种流程来分析. 简要 我们手机的桌面是一个叫做Launcher的Activity,它罗列了手机中的应用图标,图标中包含安装apk时解析的应用默认启动页等信息.在点击应用图标时,即将要启动的App和Launcher.AMS

  • Android开发App启动流程与消息机制详解

    目录 引言 1.第一步了解 ThreadLocal 2.App的启动流程 3.Activity中创建Handler 引言 相信很多人对这个问题不陌生,但是大家回答的都比较简单,如谈到app启动流程有人就会是app的生命周期去了,谈到消息机制有人就会说looper循环消息进行分发,如果是面试可能面试官不会满意,今天我们搞一篇完善的源码解析来进行阐述上面的问题 1.第一步了解 ThreadLocal 什么是ThreadLocal呢,专业的来讲,ThreadLocal 是一个线程内部的数据存储类,通过

  • Android蓝牙服务启动流程分析探索

    目录 1.SystemServer 2.BluetoothService 3.BluetoothManagerService 首先我们要知道,主要系统服务都是在 SystemServer 启动的,蓝牙也是如此: 1.SystemServer 源码路径:/frameworks/base/services/java/com/android/server/SystemServer.java private void startOtherServices(@NonNull TimingsTraceAnd

  • Android framework ATMS启动流程

    目录 1 前言 (1)ATMS 创建流程 (2)ATMS 初始化 2 ATMS 启动流程 (1)main (2)run (3)startBootstrapServices (4)startService (5)ATMS.Lifecycle 3 ATMS 初始化 (1)ATMS 的构造方法 (2)start (3)initialize (4)onActivityManagerInternalAdded (5)ActivityStartController (6)DefaultFactory 1 前

  • Eureka源码阅读解析Server服务端启动流程实例

    目录 环境 1.spring cloud整合eureka server demo 1.1 新建spring boot项目 pom.xml文件添加 配置文件 1.2 启动类 1.3 启动 2. spring cloud自动装配eureka server源码解析 2.1 @EnableEurekaServer注解 2.2 EurekaServerAutoConfiguration 2.2.1 查找starter 自动装配类的技巧 2.2.2 EurekaServerAutoConfiguration

  • 深入解析Android系统中应用程序前后台切换的实现要点

    在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的,比如说,想要给用户展示一个地图的信息,现在已经有一个Activity可以做这件事情,那么现在你的Activity需要做的就是将请求信息放进一个Intent对象里,并且将这个Intent对象传递给startActivity(),那么地图就可显示出来了,但用户按下Back键之后,你的Activi

  • 实例解析Android系统中的ContentProvider组件用法

    ContentProvider为Android四大组件之一,主要用来应用程序之间的数据共享,也就是说一个应用程序用ContentProvider将自己的数据暴露出来,其他应用程序通过ContentResolver来对其暴露出来的数据进行增删改查. ContenProvider与ContentResolver之间的对话同过Uri(通用资源标识符),一个不恰当的比喻就好像浏览器要显示一个网页要有一个东西发送请求,这相当于ContentResolver,你要拿东西就要知道去哪里拿,你就得知道服务器的域

  • 分析Android中应用的启动流程

    前言 在我们开始之前,希望您能最好已经满足以下条件: 1.有一份编译后的Android源码(亲自动手实践才会有更深入的理解) 2.对Binder机制有一定的了解 本文启动流程分析基于Android 5.1的源码.为什么是5.1的源码呢?因为手边编译完的代码只有这个版本-另外,用什么版本的源码并不重要,大体的流程并无本质上的区别,仅仅是实现细节的调整,找一个你熟悉的版本就好. 1.启动时序图 作为一个轻微强迫症的人,整理的时序图,相信大家按图索骥,一定能搞明白整个启动流程: 说明:为了让大家更清楚

随机推荐