Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


title: Android 17 BiometricService 架构与性能优化 chapter: '1.24' section: '1.24' status: finalized pipeline_stage: ready-to-publish applicable_versions: Android 12 (API 31) - Android 17 (API 37) last_verified: '2026-08-18' last_verified_against: AOSP android-17.0.0_r1 confidence: high sources:

  • type: aosp path: frameworks/base/core/java/android/hardware/biometrics/BiometricPrompt.java
  • type: aosp path: frameworks/base/core/java/android/hardware/biometrics/BiometricManager.java
  • type: aosp path: frameworks/base/core/java/android/hardware/biometrics/IAuthService.aidl
  • type: aosp path: frameworks/base/core/res/AndroidManifest.xml
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/AuthService.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/BiometricService.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/PreAuthInfo.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/AuthSession.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/BiometricSensor.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/BiometricHandlerProvider.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java
  • type: aosp path: frameworks/base/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
  • type: aosp path: frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
  • type: aosp path: frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
  • type: aosp path: hardware/interfaces/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
  • type: aosp path: hardware/interfaces/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
  • type: aosp path: hardware/interfaces/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
  • type: aosp path: hardware/interfaces/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
  • type: aosp path: hardware/interfaces/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
  • type: official path: developer.android.com/reference/android/hardware/biometrics/BiometricManager
  • type: official path: developer.android.com/reference/android/hardware/biometrics/BiometricPrompt
  • type: aosp-doc path: source.android.com/docs/security/features/biometric
  • type: aosp-doc path: source.android.com/docs/security/features/authentication tags:
  • biometric
  • system-service
  • architecture
  • fingerprint
  • face
  • hal
  • tee
  • performance related_chapters:
  • '1.10'
  • '1.23'
  • '21.4'
  • '20.10'

Android 17 BiometricService 架构与性能优化

版本范围是 Android 17 / API 37 / AOSP android-17.0.0_r1。这里讨论应用通过系统认证面板 BiometricPrompt 发起的认证;锁屏直接调用 FingerprintManager、录入流程和厂商私有解锁通道属于其他路径。

BiometricService 是一次 BiometricPrompt 会话的仲裁者,但它并非应用直接访问的第一个 Binder 服务,也不执行图像采集和模板匹配。应用入口、系统策略、会话状态、传感器队列、认证 UI 与安全执行环境分属不同组件。定位“生物识别慢”时,需要判断时间消耗落在哪一段。

Android 17 的真实调用链

进程与接口边界

下文保留几组与源码一一对应的术语。provider 管理一种模态的一组传感器,BiometricScheduler 为单个传感器串行调度任务。client 表示一次认证、录入或枚举任务,operation 表示 client 发给 HAL 的具体操作,session 是 framework 与 HAL 为当前用户复用的会话接口。HAL(硬件抽象层)连接 Android framework 与厂商实现;AIDL 用于当前稳定接口,HIDL 是旧版接口技术,Android 17 仍保留兼容适配。HAT(HardwareAuthToken)是安全环境生成、可供 Keystore 验证的认证令牌。

进程图展示了 SDK、system_server、SystemUI、HAL 与安全环境各自负责的部分:

App process
  BiometricPrompt / BiometricManager
          │ IAuthService
          ▼
system_server
  AuthService
    ├─ 权限、AppOps、前台状态与 PromptInfo 检查
    └─ 调用内部 IBiometricService
          ▼
  BiometricService
    ├─ PreAuthInfo:计算当前可用认证器
    ├─ AuthSession:管理一次 Prompt 会话
    └─ BiometricSensor:包装已注册认证器
          │ IBiometricAuthenticator
          ├──────────────────────────────┐
          ▼                              ▼
  FingerprintService                FaceService
    → Provider                        → Provider
    → per-sensor Scheduler            → per-sensor Scheduler
    → AuthenticationClient            → AuthenticationClient
          │ AIDL ISession,或旧 HAL 兼容适配
          ▼
vendor biometric HAL process
          │ vendor-defined secure channel
          ▼
secure isolated environment
  采集保护、模板保护、匹配、Strong 认证的 HAT 生成

system_server ── IStatusBarService ──► SystemUI process
  AuthSession                          AuthController / AuthContainerView
       ◄──────── IBiometricSysuiReceiver ────────┘

其中有四个需要区分的边界:

  1. BiometricPrompt.Builder.build()Context.AUTH_SERVICE 取得 IAuthService。普通应用不直接持有 IBiometricService
  2. AuthServiceBiometricService 都在 system_server,前者是 SDK 入口与访问控制层,后者是内部仲裁层。
  3. AuthController 运行在独立的 SystemUI 进程,不属于 system_server
  4. HAL 运行在 vendor 侧进程;采集、模板与匹配的安全要求由安全隔离环境及厂商实现满足。TEE 是 Trusted Execution Environment(可信执行环境),不能把 HAL 进程本身称为 TEE。

对应源码入口:

  • BiometricPrompt.Builder.build()core/java/android/hardware/biometrics/BiometricPrompt.java
  • AuthService.onStart():发布 Context.AUTH_SERVICE
  • BiometricService.onStart():发布内部 Context.BIOMETRIC_SERVICE
  • AuthController:实现 CommandQueue.Callbacks,接收状态栏 Binder 命令。

authenticate() 如何进入系统

BiometricPrompt.authenticate() 在应用进程完成参数检查,保存调用方提供的 Executor(决定回调在哪个线程执行)和 AuthenticationCallback,然后调用:

final long authId = mService.authenticate(
        mToken,
        operationId,
        userId,
        mBiometricServiceReceiver,
        mContext.getPackageName(),
        promptInfo);

这段代码用于确认两个事实:

  • CryptoObject 存在时,operationId 来自关联的加密操作;没有 CryptoObject 时为 0
  • 内部返回值是请求 ID,用于后续取消和回调关联。公开的 authenticate() 仍以异步回调向应用报告结果。

AuthService.authenticate() 随后检查:

  • 同用户调用所需的生物识别权限;跨用户调用所需的内部权限;
  • AppOps 是否允许;
  • token、receiver、包名和 PromptInfo 是否为空;
  • 调用 UID/PID 是否位于前台;
  • 非公开、测试或高级 prompt 选项所需的额外权限。

通过检查后,AuthService 清除来访 Binder identity,避免后续系统内部调用继续沿用应用身份,再把请求交给内部 BiometricServiceBiometricServiceWrapper.authenticate() 只做内部权限、参数和认证器配置检查,然后把后续工作投递到专用 Handler 所在线程。它不会在应用 Binder 调用栈中等待传感器完成。

因此,authenticate() 调用返回快,只能说明请求已被系统接受,不能说明认证器已经开始采集。

新请求如何处理旧会话

Android 17 的 BiometricService 只有一个 mAuthSession。创建新会话时,如果旧会话还在,authenticateInternal() 会强制取消旧会话、关闭旧 UI,并向旧客户端返回取消。

这与“所有 App 认证请求都在 BiometricService 排队”不同。队列存在于每个传感器的 BiometricScheduler;BiometricPrompt 层的新会话会替换旧会话。公开 API 文档也明确指出:已有认证进行时再次调用 authenticate(),旧客户端会收到取消。

应用不应在配置变化、重复点击或状态重组时快速执行“取消—重建—认证”。这种写法会产生界面重建、HAL 取消确认以及 scheduler 队列清理开销,还会让一次用户操作产生多份互相覆盖的回调。

预认证:PreAuthInfo 决定谁有资格参与

BiometricService.handleAuthenticate() 先创建 PreAuthInfo。它读取请求、传感器属性、用户状态和系统策略,生成:

  • eligibleSensors:本次可以参与的传感器;
  • ineligibleSensors:传感器及其不可用原因;
  • credentialRequested / credentialAvailable
  • 是否需要确认;
  • 生物识别强度和 Identity Check(在受保护场景要求强生物识别的系统能力)相关状态。

资格判断项

检查项Android 17 的判断依据常见结果
请求强度BIOMETRIC_STRONGBIOMETRIC_WEAK 等位掩码(bit field)传感器强度不足
运行时强度OEM 声明强度与 BiometricStrengthController 更新值安全更新前需降级
硬件状态isHardwareDetected()硬件不可用
录入状态hasEnrolledTemplates()尚未录入
锁定状态getLockoutModeForUser();预认证分支显式挡下限时锁定限时锁定;永久锁定还可能通过后续 sensor error/lockout 回调进入会话处理
用户设置是否允许应用使用该模态对 App 禁用
设备策略DPM(Device Policy Manager,设备策略管理器)是否禁用指纹、人脸或虹膜被管理策略禁用
人脸相机相机可用性和相机隐私开关相机不可用或隐私限制
设备凭据TrustManager.isDeviceSecure()PIN/图案/密码不可用
显示环境外接或受控虚拟显示相关策略当前显示不允许认证

canAuthenticate(authenticators) 复用这类信息计算公开结果。它是调用时刻的状态快照,不会预留传感器,也不保证稍后的 authenticate() 一定成功。前后台状态、相机隐私、锁定、用户切换、另一个认证会话和 HAL 健康状态都可能在两次调用之间变化。

正确的应用策略是:

  • canAuthenticate() 决定是否展示入口或引导录入;
  • 仍以 AuthenticationCallback 作为本次认证的最终结果;
  • 不因为预检查成功而忽略错误回调。

强度由安全等级决定

指纹、人脸是认证模态;Class 3、Class 2、Class 1 是安全等级。二维相机不自动等于 Class 2,深度相机也不自动等于 Class 3。设备实现必须按 CDD(Compatibility Definition Document,兼容性定义文档)的架构安全与抗欺骗要求声明并通过测试。

Android API 的能力边界是:

类型BiometricPromptKeystore 定时授权Keystore 单次操作授权
BIOMETRIC_STRONG / Class 3支持支持支持
BIOMETRIC_WEAK / Class 2支持不支持不支持
Class 1 / Convenience不进入公开 BiometricPrompt API不支持不支持
DEVICE_CREDENTIAL支持支持支持

BiometricSensor.getCurrentStrength() 将 OEM 声明值与运行时更新值按位掩码合并,结果不会比 OEM 初始声明更强。安全更新导致的降级会直接影响 PreAuthInfo 的资格判断。

API 37 增加了受角色和权限限制的 BiometricManager.getBiometricSensorStrengths()。调用方必须位于前台,同时持有 USE_BIOMETRIC 和角色授予的 ACCESS_BIOMETRIC_SENSOR_STRENGTHS;框架权限注释列出的授予范围是钱包、设备策略管理,以及便于测试的 system shell。返回结果把每种模态映射到 BIOMETRIC_STRONGLESS_THAN_STRONG,不会向调用方暴露 Class 3 以下的细分等级。普通应用仍应使用 canAuthenticate()

传感器发现、注册与会话复用

注册从 AuthService.onStart() 发起

Android 17 源码在 AuthService 中给出了注册顺序:

AuthService.onStart()
  → registerAuthenticators()
    → FingerprintService.registerAuthenticators()
      → providers → sensors
        → BiometricService.registerAuthenticator()
    → FaceService.registerAuthenticators()
      → providers → sensors
        → BiometricService.registerAuthenticator()
    → IrisService.registerAuthenticators()

BiometricServiceCopyOnWriteArrayList<BiometricSensor> mSensors 保存注册结果。源码中没有 SensorListState

Android 17 优先支持稳定 AIDL HAL,同时仍有 HIDL 配置和 HidlToAidlSessionAdapter 等兼容路径。分析具体设备时,应查看 provider 类型和 HAL instance(已注册的 HAL 服务实例),不能仅凭系统版本断定设备必走 AIDL。

BiometricSensor 保存什么

每个 BiometricSensor 只包装仲裁所需的少量状态:

  • idmodality
  • OEM 声明强度和运行时强度;
  • IBiometricAuthenticator impl
  • 当前 sensor state;
  • 用于关联准备请求与回调的 cookie,以及最近错误。

它不持有模板内容,也没有 lockoutState 字段。锁定状态通过对应 sensor service/provider 查询,并由 sensor 侧 tracker(状态跟踪器)与 AuthSessionCoordinator 协调。

AIDL session 并非每次认证都重建

Fingerprint 和 Face AIDL 的每个 sensor 都维护 mCurrentSession,provider 通过这些 sensor 与 scheduler 驱动当前用户的 HAL 会话。用户匹配且 session 健康时,认证 client 复用它;切换用户、HAL 死亡或 session 关闭时才创建或替换。

创建路径的接口形态是:

interface IFingerprint {
    SensorProps[] getSensorProps();
    ISession createSession(int sensorId, int userId, ISessionCallback cb);
}

interface IFace {
    SensorProps[] getSensorProps();
    ISession createSession(int sensorId, int userId, ISessionCallback cb);
}

所以,不能把 createSession() 固定计入每次 BiometricPrompt 延迟。若 trace 中出现用户切换、HAL 重连或 start-user client(为新用户建立 HAL 会话的任务),应单独标记为冷路径。

两层状态机:Prompt 会话与单个传感器

AuthSession 管理整次 Prompt

Android 17 的主要 session state 为:

状态含义
STATE_AUTH_IDLE尚未准备认证
STATE_AUTH_CALLED已让候选传感器准备,等待 cookie
STATE_AUTH_STARTED非指纹传感器已可启动,Prompt 已请求显示
STATE_AUTH_STARTED_UI_SHOWINGUI 动画完成,允许启动指纹
STATE_AUTH_PAUSED可重试模态暂停
STATE_AUTH_PAUSED_RESUMING正在为重试重新准备传感器
STATE_AUTH_PENDING_CONFIRM匹配成功,等待用户显式确认
STATE_AUTHENTICATED_PENDING_SYSUI已认证,等待 SystemUI 完成收尾
STATE_ERROR_PENDING_SYSUI错误已暂存,等待 UI 完成展示
STATE_SHOWING_DEVICE_CREDENTIAL转入 PIN、图案或密码

客户端 Binder 死亡时还会进入 STATE_CLIENT_DIED_CANCELLING 清理路径。源码的 @IntDef 没有把这个值列入主状态集合,但处理分支存在。

AuthSession 只有一个 mState。源码中没有 AUTH_STARTED_FACEAUTH_STARTED_FINGERPRINT 这类并行 session state。多传感器进度由每个 BiometricSensor 的状态分别记录。

BiometricSensor 管理单个传感器

单传感器状态为:

UNKNOWN
  → WAITING_FOR_COOKIE
  → COOKIE_RETURNED
  → AUTHENTICATING
  → CANCELING
  → STOPPED

cookie 是一次准备请求的关联值,用来把以下三层动作对应起来:

  1. AuthSession 为每个 eligible sensor 生成非零 cookie。
  2. BiometricSensor.goToStateWaitingForCookie() 调用 prepareForAuthentication()
  3. 对应 provider 创建 authentication client,并把它放入该传感器的 scheduler。
  4. client 到达队首且可以开始时,scheduler 通过 onReadyForAuthentication(requestId, cookie) 通知 BiometricService
  5. 所有 cookie 返回后,AuthSession 再调用 startPreparedClient(cookie)

这套“准备—就绪—启动”握手避免 Prompt 仲裁层在 sensor operation 尚未到达队首时提前启动 HAL。

启动顺序经过 UI 协调

Android 17 的启动顺序并非简单地“指纹和人脸同时开始”:

goToInitialState()
  → 所有 eligible sensors 执行 prepare
  → 等待所有 cookie 返回
  → 先启动非指纹传感器
  → 请求 SystemUI 显示 Prompt
  → SystemUI 入场动画完成
       ├─ onDialogAnimatedIn(startFingerprintNow = true)
       │    → 启动已准备的指纹
       └─ startFingerprintNow = false
            → 继续延后
            → SystemUI 稍后调用 onStartFingerprintNow()

源码注释说明了延后指纹的原因:避免指纹交互提示(affordance)在 BiometricPrompt UI 完成入场前出现。人脸可以先运行;指纹是否随入场动画结束启动,由 SystemUI 根据当前 UI 和模态策略决定。

重试时 UI 已存在,AuthSession 重新准备可重试传感器,cookie 就绪后直接恢复相应传感器,不再创建第二个对话框。

线程模型与 Binder 回调

framework 线程

位置Android 17 线程主要工作
AuthService Binder 入口system_server Binder 线程权限、AppOps、前台和参数检查
BiometricService 会话逻辑BiometricsCallbackHandler串行处理 session、sensor 与 SystemUI 回调
指纹 provider/schedulerFingerprintHandler创建 client、调度单传感器操作
人脸 provider/schedulerFaceHandler创建 client、调度单传感器操作
SystemUI AuthControllerSystemUI 主线程为主创建、更新和关闭认证 UI
App callback调用方传入的 ExecutoronAuthentication*()

BiometricHandlerProviderBiometricsCallbackHandler 创建独立 HandlerThread,优先级为 THREAD_PRIORITY_DISPLAY;Face 和 Fingerprint handler 也是独立线程,优先级为 THREAD_PRIORITY_DEFAULT

Sensor HAL 回调与 SystemUI 回调到达 Binder stub(接收端接口实现)后,BiometricService 都会再次 post() 到 callback handler。这样,mAuthSession 的状态转换集中在一个串行执行上下文中,避免由多个 Binder 线程直接并发修改。

应用回调线程

BiometricPrompt 的 receiver 会执行:

mExecutor.execute(() -> {
    mAuthenticationCallback.onAuthenticationSucceeded(result);
});

onAuthenticationFailed()onAuthenticationError() 和帮助信息也遵守同一 Executor。使用 Context.getMainExecutor() 时,回调中的数据库、网络、复杂解密或页面初始化都会占用应用主线程;改用后台 Executor 时,涉及 View 的操作必须切回主线程。

BiometricScheduler:每个传感器串行调度操作

scheduler 怎样排队

每个 AIDL sensor 持有一个 BiometricScheduler,包含:

  • 一个保存待执行任务的 Deque<BiometricSchedulerOperation> mPendingOperations
  • 一个 mCurrentOperation
  • 当前用户 session;
  • 最近的 operation 记录和统计信息。

队首 operation 分两类:

  • cookie 为 0:scheduler 可以直接 start()
  • cookie 非 0:先回报 BiometricService,等待 startPreparedClient(cookie)

新 client 声明 interruptsPrecedingClients() 时,scheduler 会:

  1. 把可取消的 pending operation(待执行任务)标为 canceling;
  2. 当前 operation 已开始且可中断时,请求取消;
  3. 等当前 operation 的完成 callback 执行后,再启动队列中的下一项。

因此,“录入一定比认证优先”或“认证一定能抢占录入”都不成立。是否中断取决于具体 client 的属性、当前 operation 是否已经开始以及它是否可取消。

Fingerprint 与 Face HAL 的终止条件不同

Fingerprint AIDL 把方法分为 non-interrupting operation(同一 session 中排他执行的主要操作)和 interrupting operation(可在主要操作期间调用的交互方法)。一个 session 同时只能执行一个 non-interrupting operation;authenticate()enroll()detectInteraction() 属于可取消的 non-interrupting operation。取消后,HAL 必须用 Error::CANCELED 结束该 operation。这里的 interrupting 是 HAL 接口分类,不表示 scheduler 会抢占前一个 client。

Face AIDL 没有这组 interrupting operation 分类,接口约束是一个 session 同时只能执行一个 operation。Face 的 onAuthenticationFailed() 是终止回调;Fingerprint 的同名拒绝匹配回调不是终止回调,指纹 operation 可以继续等待下一次触摸。framework 的 scheduler 会等当前 operation 的终止回调完成,再启动下一个排队操作。

指纹 AIDL 的主要方法是:

ICancellationSignal authenticate(long operationId);
ICancellationSignal enroll(HardwareAuthToken hat);
ICancellationSignal detectInteraction();
void enumerateEnrollments();
void removeEnrollments(int[] enrollmentIds);
void generateChallenge();
void revokeChallenge(long challenge);
void resetLockout(HardwareAuthToken hat);
void close();

UDFPS(Under-Display Fingerprint Sensor,屏下指纹传感器)的 onPointerDown*()onPointerUp*()onUiReady() 等属于可在采集 operation 运行时调用的交互方法,不应和第二个 authenticate operation 混为一谈。

Face AIDL 也使用 authenticate()detectInteraction(),没有 detectInteractive()。Android 17 还提供带 OperationContext 的变体,HAL 可以利用显示、AOD(Always-On Display,息屏显示)等上下文优化执行,也可以忽略额外上下文并按基础方法处理。

不要虚构统一超时

Android 17 的 AuthSession 没有“所有认证 30~60 秒强制结束”的统一常量。超时可能来自:

  • HAL 对当前采集返回 BIOMETRIC_ERROR_TIMEOUT
  • sensor client 的具体实现;
  • SystemUI 的交互状态;
  • scheduler watchdog 的显式调用;
  • OEM HAL 或安全环境。

BiometricScheduler.startWatchdog() 中有 10 秒清理定时器,Fingerprint/Face service 也暴露了受 USE_BIOMETRIC_INTERNAL 保护的 scheduleWatchdog() 内部入口,provider 会把它转为对应 scheduler 的 startWatchdog()。这仍不是 BiometricPrompt 每次 authenticate() 自动启用的用户认证超时,不能把它描述成所有认证 10 秒或 30~60 秒强制结束。

排查超时时,应记录实际 error、modality(指纹、人脸等认证模态)、vendorCode 和当前 operation,不要套用固定秒数。

指纹、UDFPS 与人脸的性能边界

指纹路径

下面的调用链用于区分 provider 排队、client 启动和 HAL operation:

FingerprintService.prepareForAuthentication()
  → FingerprintProvider.scheduleAuthenticate()
  → FingerprintAuthenticationClient
  → per-sensor BiometricScheduler
  → AIDLSession.authenticate[WithContext](operationId)
  → ISessionCallback

provider 在自己的 handler 上构造 client。client 启动 HAL operation 后保存 ICancellationSignal;取消时调用它的 cancel(),并等待 HAL 的最终回调完成生命周期。

不要把下面这些时间合成一个“指纹算法耗时”:

  • operation 在 scheduler 队列中的等待;
  • 当前用户 AIDL session 的启动或重建;
  • Prompt 入场完成前的指纹延后;
  • UDFPS overlay(屏幕上的指纹交互层)、触摸命中、显示模式与刷新率协调;
  • HAL 采集和 secure matcher(安全环境中的匹配器);
  • 成功动画、对话框关闭与 App Executor 调度。

UDFPS 是 UI、显示和 HAL 的协作

SystemUI 的 AuthController 根据 sensor properties(传感器属性)创建 UdfpsController,维护 sensor bounds(传感器在屏幕上的区域)和 display scale(显示缩放比例),并向 framework 注册 UDFPS overlay controller。指纹 authentication client 收到 PointerContext 后调用 HAL 的 onPointerDownWithContext() 或兼容方法。

一次 UDFPS 卡顿可能发生在:

  1. Prompt 尚未完成入场;
  2. overlay 尚未就绪;
  3. 触摸未命中 sensor bounds;
  4. 显示模式或高刷新率请求尚未完成;
  5. HAL 尚未回报 acquired(样本采集状态);
  6. 采集质量不足,多次 acquired 后才匹配;
  7. 匹配完成,但成功 UI 仍在收尾。

UDFPS 延迟高度依赖面板、传感器、贴膜、亮度策略与 vendor HAL。没有硬件和 trace 证据时,不应给出跨设备通用的毫秒区间。

人脸路径

人脸采用相同的 provider/scheduler 分层,但 HAL 回调和失败终止语义与指纹不同:

FaceService.prepareForAuthentication()
  → FaceProvider.scheduleAuthenticate()
  → FaceAuthenticationClient
  → per-sensor BiometricScheduler
  → AIDLSession.authenticate[WithContext](operationId)
  → authentication frame / acquired / success / failure / error

人脸 client 可以接收 FaceAuthenticationFrame,把 acquired 信息和帮助文案交给 UI。一次拒绝匹配(reject)会结束当前 face authentication client;在 BiometricPrompt 中,AuthSession 可进入暂停状态,由用户点击重试后重新 prepare。

是否需要显式确认由三项共同决定:

  • 该 sensor 是否支持确认;
  • 用户设置是否要求该模态总是确认;
  • PromptInfo 是否请求确认。

确认策略与“二维/三维”或“Class 2/Class 3”没有固定一一映射。

多模态不是融合算法

当人脸和指纹都符合本次请求条件(eligible)时,AuthSession 可以准备多个 sensor,但 Android 17 的通用 framework 代码不执行厂商级特征融合。它协调各 sensor 的启动、UI、成功、失败和取消:

  • 非指纹 sensor 在所有 cookie 返回后先启动;
  • 指纹等待 UI 信号;
  • 任一 sensor 成功后,session 记录 mAuthenticatedSensorId
  • 无需确认时取消其他 sensor;
  • 需要确认时,源码会为特定侧边指纹场景保留传感器,其余 sensor 取消;
  • 后到的成功或错误回调会按当前 session/requestId 状态过滤。

因此,双模态设备的总延迟不能简单写成 max(face, fingerprint)。两个模态的启动时刻不同,失败后的 UI 策略也不同。

安全边界:模板、HAT 与 Keystore

framework 看不到原始模板

Android 对 Class 2 和 Class 3 生物识别要求采集、录入和识别位于安全隔离环境中。原始生物数据和模板不得暴露给 Android framework,持久化数据需要设备专属密钥保护。

framework 能看到的只有:

  • sensor metadata;
  • acquired、success、failure、error 等事件;
  • enrollment ID 等受限标识;
  • Strong 认证成功时返回的 HardwareAuthToken;
  • 用于会话协调的 requestId、cookie ID。

具体使用 TEE、Secure Element(安全元件)、StrongBox 或其他受支持安全硬件,由设备实现决定。StrongBox 主要是隔离的 KeyMint 实现和安全存储能力;它可能保存某些用户相关数据,但不能作为所有 biometric matcher 所在位置的统称。

HardwareAuthToken 的字段

Android 17 的 android.hardware.keymaster.HardwareAuthToken 包含:

challenge
userId             // secure user ID,不是 Android userId/UID
authenticatorId    // 当前录入集合对应的 secure authenticator ID
authenticatorType
timestamp
mac                // HMAC-SHA256

HAT 有两类用途:

  • 录入或解除锁定(enrollment/reset lockout):HAL 验证由设备凭据等安全认证产生的 HAT;
  • Strong 生物识别成功:HAL 用传入的 operationId 填入 challenge,生成 HAT,授权对应的 auth-per-use key operation(每次使用都要求认证的密钥操作)。

只有 Strong sensor 可以在成功回调中返回可供 Keystore 使用的 HAT。非 Strong sensor 即使回传 token,Android 17 的 AuthSession.onAuthenticationSucceeded() 也会将其丢弃。

成功回调为何晚于 HAL success

Strong sensor 成功后,AuthSession 暂存 token,并通知 SystemUI 播放成功或确认 UI。SystemUI dismiss 后:

  1. AuthSession.onDialogDismissed() 把生物识别 HAT 或设备凭据 attestation(凭据验证证明)交给 KeyStoreAuthorization.addAuthToken()
  2. 再调用应用侧 onAuthenticationSucceeded()
  3. 清理其他 sensor 和当前 session。

App 观察到的 success 时间包含 UI 收尾和 token 注入阶段。HAL 已经匹配成功,不代表 App callback 已经执行。

Gatekeeper 负责 PIN、图案和密码等设备凭据验证;设备的安全生物识别组件负责匹配;Keystore2/KeyMint 消费合适的 AuthToken。StrongBox 是隔离的 KeyMint 实现,不能据此推断 biometric matcher 也运行在 StrongBox 中。各组件共享安全认证协议,但职责不同。

失败、取消与锁定

failure、error 和 cancel 不同

结果含义会话行为
onAuthenticationFailed()采集有效但未匹配App 收到 failed;Face operation 结束并进入可重试暂停,Fingerprint operation 通常继续等待
BIOMETRIC_ERROR_TIMEOUT当前 sensor operation 超时SystemUI 以软错误处理,session 可停在可重试状态
hard error(不可恢复错误)HAL 不可用、不可恢复错误等暂存错误,等待 UI 展示后结束
App cancel调用方取消当前 requestIdsensor 进入 CANCELING,等待取消完成或强制收尾
client death(客户端死亡)App Binder 死亡取消运行中 sensor,关闭 UI
lockout(认证锁定)HAL/sensor tracker 报告限流状态允许回退到设备凭据时转到 credential UI,否则结束

CancellationSignal.cancel() 发出取消请求,不保证所有层在同一时刻停止。旧 HAL 回调仍可能到达,因此 Android 17 每次回调都用 requestId、cookie 和当前 session 过滤。

锁定由 sensor 侧报告并协调

PreAuthInfo 调用每个认证器的 getLockoutModeForUser()。AIDL HAL 可通过:

  • onLockoutTimed(durationMillis)
  • onLockoutPermanent()
  • onLockoutCleared()

报告状态。framework 的 AuthSessionCoordinatorMultiBiometricLockoutState 在不同认证强度、sensor 与用户之间协调结果。

不要把“失败 5 次锁 30 秒”写成所有设备的 framework 实现。精确要求来自当前 Android CDD,执行细节还受 sensor strength、HAL 与设备策略影响。诊断时以实际 error、duration、sensorId 和设备 CDD 版本为准。

SystemUI 与 App 的可见完成时间

AuthController 的职责

BiometricService 通过 IStatusBarService.showAuthenticationDialog()PromptInfo、sensor IDs、credential 许可、确认策略、operationId 和 requestId 传给 SystemUI。

AuthController 在 SystemUI 中:

  • 创建并持有 AuthContainerView
  • 根据 sensor properties 管理指纹、人脸、UDFPS 和凭据 UI;
  • 检查发起认证的 App 是否退到后台;
  • 把入场完成、立即启动指纹、重试、切换凭据和 dismiss(关闭对话框)事件回传给 AuthSession
  • 把 acquired、success 和 error 映射为用户可见状态。

它不会调用 biometric HAL。UdfpsController 管理 overlay 和触摸交互,实际 authenticate operation 仍由 fingerprint provider/client 驱动。

三种“完成”不能混用

时间点说明
HAL successsecure matcher 已接受样本
SystemUI successPrompt 已进入成功或确认状态
App callbacktoken 已处理,SystemUI 已按原因 dismiss,回调已进入应用 Executor

用户可能在成功动画开始时就认为认证完成,业务代码则要等 App callback。性能指标必须写明采用哪个结束点。

性能定位:先分段,再解释

建议记录的时间点

人脸可在 Prompt 入场前启动,指纹通常等待 SystemUI 信号。两种模态不能共用一条假定严格递增的时间轴。应把 App、会话、UI 和每个 sensor 分开记录:

标记事件可观测位置
A_requestApp 调用 authenticate()App 埋点
B_enterAuthService.authenticate() 接收system_server 日志或定制 trace
B_sessionPreAuthInfo 完成并创建 AuthSessionBiometricService
U_showSystemUI 开始显示 PromptAuthController.showAuthenticationDialog()
U_animatedPrompt 入场动画完成onDialogAnimatedIn()
S_prepare[id]向指定 sensor 提交 prepareprepareForAuthentication()
S_ready[id]指定 sensor 的 cookie 就绪onReadyForAuthentication()
S_start[id]对指定 sensor 调用 HAL authenticatesensor client
S_acquired[id]指定 sensor 的首个 acquired/framesensor client callback
S_reject[id]指定 sensor 报告未匹配;Fingerprint 可出现多次sensor client callback
S_end[id]operation 终止:success/error,Face 还包括 failuresensor client callback
U_dismissSystemUI dismiss 完成回调onDialogDismissed()
A_callbackApp callback 开始执行调用方 Executor

跨进程计算必须使用同一单调时钟,例如 Perfetto 的 trace clock(跟踪时钟);不能直接相减各进程记录的 wall clock(日期时间)时间戳。公开 authenticate() 也不会把内部 requestId 返回给 App,因此 App 与 system_server 的事件关联需要受控的单请求测试或自有系统埋点。并发场景下不能用“时间上最近的一条 biometric 日志”代替关联 ID。

这些标记允许在同一份 trace 中分别计算:

应用到 Binder 入口耗时   = B_enter - A_request
预认证与会话创建耗时     = B_session - B_enter
sensor 排队与准备耗时   = S_ready[id] - S_prepare[id]
sensor 启动协调耗时     = S_start[id] - S_ready[id]
首个样本等待            = S_acquired[id] - S_start[id]
当前 operation 耗时            = S_end[id] - S_start[id]
Prompt 入场耗时          = U_animated - U_show
UI 与 token 收尾          = U_dismiss - 成功 sensor 的 S_end[id]
应用调度延迟            = A_callback - U_dismiss

S_start[id] 需要从 framework client 或 vendor trace 取得。对 Face,S_start[id] 可以早于 U_show;对 Fingerprint,S_start[id] 往往不早于 U_animated。仅有 App 的 A_request/A_callback 时,只能得到端到端耗时,不能据此判断安全环境或传感器慢。

系统自带诊断入口

以下命令用于查看当前 session、已注册 sensor、provider 和 scheduler 状态:

adb shell dumpsys biometric
adb shell dumpsys fingerprint
adb shell dumpsys face

dumpsys biometric 的文本输出包含 sensor 列表和 CurrentSession。Fingerprint/Face dump 可看到 provider、当前 client、pending queue(待执行队列)和最近 operation。量产设备可能限制部分 dump 内容,userdebug/eng 构建更适合深入分析。

以下命令用于抓取 framework 与 SystemUI 事件:

adb logcat -v threadtime \
  -s BiometricService AuthService AuthController \
     FingerprintService FaceService BiometricScheduler

tag 和详细日志受构建类型、日志级别及 OEM 修改影响。采集前应在目标构建上确认实际 tag。

Perfetto 建议至少覆盖:

  • sched、线程唤醒与 CPU frequency;
  • Binder driver;
  • system_server 与 SystemUI;
  • gfx/view/window 相关轨道;
  • 相机与 vendor biometric/TEE 自定义 data source(跟踪数据源)。

Android 17 的 BiometricServiceAuthSessionAuthController 主路径没有稳定的专用 Trace.traceBegin() slice 可作为跨设备契约。不要把厂商 trace 名称写成 AOSP 保证;需要时在自有系统构建中给上述 App、UI 和 sensor 边界增加成对 trace。

症状到证据的映射

症状先看什么常见原因
点击后迟迟不弹窗A_requestU_show、前台状态/AppOps、PreAuthInfo主线程阻塞、策略检查失败、旧会话取消、SystemUI 忙
弹窗出现后指纹才慢慢亮S_readyS_startU_showU_animated、UDFPS overlay/显示模式UI 协调或显示准备,不一定是 matcher
有提示但迟迟不成功acquired/reject 序列、S_startS_end样本质量、环境、HAL 或 secure matcher
已显示成功,业务页面仍未继续成功 sensor 的 S_endA_callback成功动画、HAT 注入、App Executor 排队
第二次认证特别慢旧 requestId、cancel 完成、scheduler 当前任务快速重启导致清理与新请求竞争
偶发立即转 PINlockout error、credentialAllowed限时/永久锁定或传感器策略
人脸不可用但指纹正常相机隐私开关、eligibleSensors相机隐私、相机占用、模态单独禁用

App 侧写法

下面的示例只展示生命周期和回调线程边界。它不把 canAuthenticate() 当成认证保证,也不在回调里执行重任务:

class LoginActivity : ComponentActivity() {
    private var cancellationSignal: CancellationSignal? = null

    fun requestBiometricLogin() {
        if (cancellationSignal != null) return

        val signal = CancellationSignal()
        cancellationSignal = signal

        val prompt = BiometricPrompt.Builder(this)
            .setTitle("确认身份")
            .setAllowedAuthenticators(
                BiometricManager.Authenticators.BIOMETRIC_STRONG or
                    BiometricManager.Authenticators.DEVICE_CREDENTIAL
            )
            .build()

        prompt.authenticate(
            signal,
            mainExecutor,
            object : BiometricPrompt.AuthenticationCallback() {
                override fun onAuthenticationSucceeded(
                    result: BiometricPrompt.AuthenticationResult
                ) {
                    cancellationSignal = null
                    continueLogin()
                }

                override fun onAuthenticationError(
                    errorCode: Int,
                    errString: CharSequence
                ) {
                    cancellationSignal = null
                    renderAuthenticationError(errorCode, errString)
                }

                override fun onAuthenticationFailed() {
                    showTryAgainHint()
                }
            }
        )
    }

    override fun onDestroy() {
        if (isFinishing) {
            cancellationSignal?.cancel()
            cancellationSignal = null
        }
        super.onDestroy()
    }
}

示例用 mainExecutor,所以三个回调都应保持短小。若成功后要读数据库、访问网络或执行较重的密码学业务,应把任务交给后台执行器,再把 UI 结果送回主线程。

还要注意:

  • onAuthenticationFailed() 通常不是终止回调,不要在这里立即创建新的 Prompt;
  • 终止后由 success 或 error 清理本地进行中状态;
  • 是否在 onDestroy() 取消要结合页面保留策略;配置变化时反复销毁重建会造成不必要的取消;
  • CryptoObject 使用的认证器要和密钥生成时的授权配置一致。

版本边界

版本相关变化
Android 9 / API 28引入 framework BiometricPrompt
Android 11 / API 30公开 BiometricManager.Authenticators,可组合 biometric 与 device credential
Android 12 / API 31AOSP 文档明确纳入 UDFPS 支持;适用范围从该版本开始
Android 13 起新设备实现逐步迁移到稳定 AIDL biometric HAL
Android 17 / API 37当前源码锚点;包含 Identity Check 资格处理、受限 sensor strength 查询和现代 AIDL session context(会话上下文)能力

Android 17 仍保留旧设备 HAL 兼容适配。版本号只能说明 framework 能力上限,不能替代目标设备的 provider、HAL interface version、sensor properties 和 vendor 实现核查。

源码核查索引

问题Android 17 源码
App 为何先进入 AuthServiceBiometricPrompt.javaIAuthService.aidlAuthService.java
谁计算 eligible sensorPreAuthInfo.java
谁保存当前 Prompt 会话BiometricService.javamAuthSession
session 与 sensor 状态是什么AuthSession.javaBiometricSensor.java
callback 在哪个线程运行BiometricHandlerProvider.javaBiometricPrompt.java
operation 为何串行BiometricScheduler.java、AIDL ISession.aidl
AIDL session 是否复用Fingerprint/Face aidl/Sensor.java*StartUserClient.java
UDFPS 如何传 pointerFingerprintAuthenticationClient.javaUdfpsController.java
HAT 何时交给 KeystoreAuthSession.onDialogDismissed()
SystemUI 如何参与AuthController.javaAuthContainerView.java

官方资料:

与关联章节的分工

章节分工
§1.10 Binder 线程池与优先级继承Binder 调度和优先级传播
§8.5 Keystore/KeyMint密钥授权、CryptoObject、KeyMint 与 StrongBox
§8.5 BiometricPrompt 登录性能登录业务的端到端指标和线上观测
§20.10 Keystore 治理密钥生命周期、失效与异常治理

小结

Android 17 的 BiometricPrompt 路径可以归纳为四个控制点:

  1. AuthService 处理公开入口的访问控制;
  2. BiometricServicePreAuthInfo 和单个 AuthSession 仲裁请求;
  3. 每个 sensor 的 provider 与 BiometricScheduler 串行驱动 HAL operation;
  4. SystemUI 控制用户可见流程,安全环境完成受保护的采集、匹配与 HAT 生成。

一次慢认证可能卡在旧会话取消、预认证、scheduler、AIDL session 冷启动、Prompt 动画、UDFPS 显示协作、首个样本、secure matcher、HAT 注入或 App Executor。把 App、UI 和各 sensor 的分段标记采齐,再对照当前 requestId、sensorId、operation 和 error,才能把问题归到负责的组件。