上半年在实习没有更博,做了与手机指纹认证相关的项目,由于项目需要阅读了 AOSP 相应部分的源码,在这篇博文里做一个系统化的整理~
安卓生物识别架构
Android Q(10) 开始引入了 BiometricManager
类,本文基于这一架构,结合最新的 AOSP 源码介绍安卓的指纹识别架构,侧重与发起指纹认证相关的方法(非其它生物认证方式或录入流程)。
Android Code Search: https://cs.android.com/
BiometricManager
frameworks/base/core/java/android/hardware/biometrics/BiometricManager.java
/**
* A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}.
*/
-
static final 成员变量:定义在
BiometricConstants
类中的SUCCESS
,ERROR_HW_UNAVAILABLE
,ERROR_NONE_ENROLLED
,NO_HARDWARE
-
构造函数:传入
Context
,IAuthService
(Communication channel fromBiometricPrompt
andBiometricManager
toAuthService
)AuthService: System service that provides an interface for authenticating with biometrics and PIN/pattern/password to BiometricPrompt and lock screen.
在系统层,根据认证类型注册相应的服务(FingerprintService, FaceService, IrisService),做检查权限等
-
接口
Authenticators
:认证类型的结合(e.g.DEVICE_CREDENTIAL | BIOMETRIC_WEAK
),包含生物认证的强度(STRONG
,WEAK
),用于设备保护的非生物认证方式(DEVICE_CREDENTIAL
: PIN, pattern, password) -
canAuthenticate
,hasEnrolledBiometrics
方法:检查设备是否支持生物识别身份验证,是否有录入的生物特征,以及相应的权限检查
BiometricPrompt
frameworks/base/core/java/android/hardware/biometrics/BiometricPrompt.java
/**
* A class that manages a system-provided biometric dialog.
*/
-
私有成员变量
-
用于请求:
IAuthService
类型的mService
,在构造函数中根据认证类型被赋值mService = IAuthService.Stub.asInterface( // 得到一个IAuthService实例 ServiceManager.getService(Context.AUTH_SERVICE));
-
用于接收:
IBiometricServiceReceiver
类型的 final 变量mBiometricServiceReceiver
,其中的方法实现为根据系统服务返回的认证结果选择mAuthenticationCallback
中的回调执行;private final IBiometricServiceReceiver mBiometricServiceReceiver = new IBiometricServiceReceiver.Stub() { @Override public void onAuthenticationSucceeded(@AuthenticationResultType int authenticationType) throws RemoteException { mExecutor.execute(() -> { final AuthenticationResult result = new AuthenticationResult(mCryptoObject, authenticationType); mAuthenticationCallback.onAuthenticationSucceeded(result); }); } @Override ... }
mAuthenticationCallback
为 ` AuthenticationCallback类型,在私有方法
authenticateInternal` 中被赋值 -
…
-
-
抽象内部类
AuthenticationCallback
:包含onAuthenticationError
,onAuthenticationHelp
(可恢复的错误,如“传感器脏了”),onAuthenticationSucceed
,onAuthenticationFailed
等方法,用户可以定制化实现监听到相应事件时要做的;在调用authenticate(User)
方法时传入 -
内部类
OnAuthenticationCancelListener
:CancellationSignal.OnCancelListener
接口函数的实现,调用私有方法cancelAuthentication
,其中通过mService
调用系统服务中的cancelAuthentication
方法 -
authenticate
/authenticateUser
方法:主要传入的参数有CancellationSignal
类型的cancel
和AuthenticationCallback
类型的callback
,调用私有方法authenticateInternal
完成(1) 给
cancel
注册一个监听器,为OnAuthenticationCancelListener
类的实例;(2) 将
mBiometricServiceReceiver
依赖的mAuthenticationCallback
赋值为应用实现的callback
;(3) 通过
mService
,传mBiometricServiceReceiver
去调用系统服务中的authenticate
方法;(4) 若在上述过程中有错误发生,则使用
callback
报告“硬件不可达”的错误 -
内部类
Builder
和ButtonInfo
,以及返回值类型是它们的方法:处理与系统对话框相关的事务
总结:应用创建 BiometricPrompt
实例时,会通过 AIDL 拥有一个和系统层认证服务沟通的对象 mService
。当调用 authenticate(User)
发起认证时,需要传入一个能终止进行中的系统操作的 cancel
“开关”、定义了不同认证结果回调行为的 callback
,接下来 BiometricPrompt
类内部会做的事主要有
(1) 给 cancel
开关装上监听器,用于开关被按下时通过 mService
告知系统服务去取消认证
(2) 将 callback
的约定包装进用于传回系统认证结果的(AIDL 定义的)接收器
(3) 将包装好的接收器作为参数,通过 mService
向系统服务发起认证请求
至此的两个类是应用可单独创建实例的,接下来介绍系统服务。与上层直接沟通的 AuthService
实现了 AIDL 定义的 authenticate
, cancelAuthentication
等方法。
private final class AuthServiceImpl extends IAuthService.Stub { // 实现 .aidl 生成的接口:扩展生成的 Binder 接口(<Interface>.Stub),并实现继承自 .aidl 文件的方法。
@Override
public void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle)
throws RemoteException {
...
try {
mBiometricService.authenticate(
token, sessionId, userId, receiver, opPackageName, bundle, callingUid,
callingPid, callingUserId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
...
}
在 AuthService.authenticate
方法中调用了 BiometricService.authenticate
,其中实例 mBiometricService
在服务启动时通过 registerAuthenticator
,使用认证类型对应的服务(如FingerprintService
)进行了注册。
FingerprintService
frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
/**
* A service to manage multiple clients that want to access the fingerprint HAL API.
* The service is responsible for maintaining a list of clients and dispatching all
* fingerprint-related events.
*
* @hide
*/
-
构造函数:初始化与错误 延时/总数 计数器相关的变量
mTimedLockoutCleared
,mFailedAttempts
-
私有成员变量
-
mDaemon
:IBiometricsFingerprint
类型,用于请求厂商库(支持authenticate
,cancel
等方法) -
mDaemonCallback
:IBiometricsFingerprintClientCallback
类型/** * Receives callbacks from the HAL. */ private IBiometricsFingerprintClientCallback mDaemonCallback = new IBiometricsFingerprintClientCallback.Stub() { @Override // onAuthenticated: FingerprintService.super.handleAuthenticated(authenticated, fp, token); // onError: FingerprintService.super.handleError(deviceId, error, vendorCode); ... };
收到认证结果时调用父类BiometricServiceBase
中的方法handleAuthenticated
或handleError
protected void handleAuthenticated(boolean authenticated, BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token) { ... /* if (authenticated) { mPerformanceStats.accept++; } else { mPerformanceStats.reject++; // 失败次数+1 } */ } protected void handleError(long deviceId, int error, int vendorCode) { ... if (client != null && client.onError(deviceId, error, vendorCode)) { removeClient(client); } if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) { mHandler.removeCallbacks(mResetClientState); ... } }
Android 12 更新: 计数器位于
PerformanceTracker
类private static class Info { int mAccept; // number of accepted biometrics int mReject; // number of rejected biometrics int mAcquire; // total number of acquisitions. int mAcceptCrypto; int mRejectCrypto; int mAcquireCrypto; int mTimedLockout; // total number of lockouts int mPermanentLockout; // total number of permanent lockouts } // Keyed by UserId private final SparseArray<Info> mAllUsersInfo; private int mHALDeathCount;
-
-
私有方法
getFingerprintDaemon
:根据 HIDL 的定义,获得厂商库支持的认证服务,并用mDaemonCallback
接收 HAL 的返回/** Gets the fingerprint daemon */ private synchronized IBiometricsFingerprint getFingerprintDaemon() { if (mDaemon == null) { Slog.v(TAG, "mDaemon was null, reconnect to fingerprint"); try { mDaemon = IBiometricsFingerprint.getService(); } ... try { mHalDeviceId = mDaemon.setNotify(mDaemonCallback); } // Failed to open fingerprint HAL, try again later! }... } return mDaemon; }
-
<Deprecated: 通信上层
FingerprintManager
时使用> 私有内部类FingerprintAuthClient
:包含
isStrongBiometric
,resetFailedAttempts
,handleFailedAttempt
等方法public int handleFailedAttempt() { // 给用户的失败次数计数器+1 final int currentUser = ActivityManager.getCurrentUser(); mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1); mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false); if (getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { scheduleLockoutResetForUser(currentUser); } return super.handleFailedAttempt(); }
Fingerprint HAL
hardware/interfaces/biometrics/fingerprint/2.1/
IBiometricsFingerprint.hal 中的方法:供应商库中负责实现
IBiometricsFingerprintClientCallback.hal 中的方法:在 FingerprintService
中实现(参见mDaemonCallback
)
参考: