由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章(也可以点击 RSS 订阅查看代码更方便),希望这篇文章能帮你梳理清楚“指纹注册流程”。
关键类 | 路径 |
---|---|
FingerprintEnrollIntroduction.java | packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java |
BiometricEnrollIntroduction.java | packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java |
FingerprintEnrollEnrolling.java | packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java |
BiometricsEnrollEnrolling.java | packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java |
FingerprintEnrollSidecar.java | packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java |
BiometricEnrollSidecar.java | packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollSidecar.java |
FingerprintEnrollFindSensor.java | packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java |
FingerprintManager.java | frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java |
FingerprintService.java | frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java |
BiometricServiceBase.java | frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java |
EnrollClient.java | frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java |
关键类 | 说明 |
---|---|
BiometricEnrollBase | 指纹录制的基类。 |
FingerprintEnrollFindSensor | 指纹开始准备录入的 Activity,继承 BiometricEnrollBase 。 |
FingerprintEnrollSidecar | 注册 EnrollmentCallback ,监听指纹录入状态,继承 BiometricEnrollSidecar 。 |
FingerprintEnrollEnrolling | 指纹录入过程的 Activity,继承 BiometricEnrollBase 类。 |
FingerprintEnrollFinish | 指纹录制结束后调用的 Activity,继承 BiometricEnrollBase 类。 |
FingerprintRemoveSidecar | 管理指纹删除操作。 |
FingerprintFindSensorAnimation | 指纹动画接口。 |
FingerprintLocationAnimationView | 指纹动画,实现了 FingerprintFindSensorAnimation 接口。 |
本篇文章,我们从源码角度探讨指纹录入的过程(测试样机:Pixel),我们先看下 UI 图,这个你应该不陌生了。
接下来我们就从指纹引导界面开始源码分析,图 1 的逻辑就在 FingerprintEnrollIntroduction
类,点击 Next
执行下一步,会执行 onNextButtonClick()
方法。
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
// Cancel Button
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_introduction_cancel)
.setListener(this::onCancelButtonClick)
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
// Next Button
mFooterBarMixin.setPrimaryButton(
new FooterButton.Builder(this)
.setText(R.string.wizard_next)
.setListener(this::onNextButtonClick) // 点击 "下一步" 的处理流程
.setButtonType(FooterButton.ButtonType.NEXT)
.setTheme(R.style.SudGlifButton_Primary)
.build()
);
}
}
我们可以发现:FingerprintEnrollIntroduction
继承自 BiometricEnrollIntroduction
,onNextButtonClick()
方法在其父类 BiometricEnrollIntroduction
中处理。
// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
implements LinkSpan.OnClickListener {
@Override
protected void onNextButtonClick(View view) {
mNextClicked = true;
if (checkMaxEnrolled() == 0) {
// Lock thingy is already set up, launch directly to the next page
launchNextEnrollingActivity(mToken); // 接下来就要拉起指纹录入界面
} else {
setResult(RESULT_FINISHED);
finish();
}
}
}
// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
implements LinkSpan.OnClickListener {
private void launchNextEnrollingActivity(byte[] token) {
Intent intent = getEnrollingIntent(); // 获取 FingerprintEnrollFindSensor
if (token != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
}
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary);
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST); // 跳转 FingerprintEnrollFindSensor
}
}
我们看下 getEnrollingIntent()
方法:
// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
implements LinkSpan.OnClickListener {
protected abstract Intent getEnrollingIntent(); // 抽象方法,由子类 FingerprintEnrollIntroduction 实现
}
所以我们跳转到 FingerprintEnrollIntroduction
:
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected Intent getEnrollingIntent() {
return new Intent(this, FingerprintEnrollFindSensor.class); // 获取 FingerprintEnrollFindSensor
}
}
我们把上面的图再拿过来,此时就进入了图 2 界面的逻辑,我们接着往下看。
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentView());
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
// Skip button
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
.setText(R.string.skip_label)
.setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
// Touch the sensor
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
// 执行 startLookingForFingerprint() 方法
startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
// 演示动画
View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
if (animationView instanceof FingerprintFindSensorAnimation) {
mAnimation = (FingerprintFindSensorAnimation) animationView;
} else {
mAnimation = null;
}
}
}
到这里都只是涉及到 UI 界面的相关逻辑,接下来的代码逻辑就稍微复杂一点了,我们仔细深挖研究。
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
private FingerprintEnrollSidecar mSidecar;
private boolean mNextClicked;
private void startLookingForFingerprint() {
// FingerprintEnrollSidecar 这个 fragment 的生命周期正式开启
mSidecar = (FingerprintEnrollSidecar) getSupportFragmentManager().findFragmentByTag(
FingerprintEnrollEnrolling.TAG_SIDECAR);
if (mSidecar == null) {
mSidecar = new FingerprintEnrollSidecar();
// 添加 FingerprintEnrollEnrolling
getSupportFragmentManager().beginTransaction()
.add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR)
.commitAllowingStateLoss();
}
// FingerprintEnrollEnrolling 实现了 BiometricEnrollSidecar.Listener 接口
mSidecar.setListener(new Listener() { // 匿名内部类的方式实现接口方法
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
mNextClicked = true;
proceedToEnrolling(true /* cancelEnrollment */);
}
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
mNextClicked = false;
proceedToEnrolling(false /* cancelEnrollment */);
}
}
});
}
}
这里面有个重点方法:onEnrollmentProgressChange()
,如果我们此时用手指贴在指纹传感器上,会产生反馈信息的回调,此时 onEnrollmentProgressChange()
方法被执行,进入执行 proceedToEnrolling()
方法,我们看下这个方法:
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
private void proceedToEnrolling(boolean cancelEnrollment) {
if (mSidecar != null) {
if (cancelEnrollment) {
if (mSidecar.cancelEnrollment()) {
// Enrollment cancel requested. When the cancellation is successful,
// onEnrollmentError will be called with FINGERPRINT_ERROR_CANCELED, calling
// this again.
return;
}
}
getSupportFragmentManager().beginTransaction().remove(mSidecar).
commitAllowingStateLoss();
mSidecar = null;
// getFingerprintEnrollingIntent() 方法会返回一个包含 FingerprintEnrollEnrolling 的 Intent
startActivityForResult(getFingerprintEnrollingIntent(), ENROLL_REQUEST);
}
}
}
正常流程会走到 startActivityForResult()
方法,跳转到 FingerprintEnrollEnrolling
界面。
我们把上面的图再拿过来,此时就进入了图 3 界面的逻辑,我们接着往下看。
我们重点关注 onStart()
方法:
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
/**
* Activity which handles the actual enrolling for fingerprint.
*/
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected void onStart() {
super.onStart(); // 调用父类 BiometricEnrollSidecar 的 onStart() 方法
updateProgress(false /* animate */); // 更新录入进度
updateDescription();
if (mRestoring) {
startIconAnimation();
}
}
}
FingerprintEnrollEnrolling
类继承自 BiometricsEnrollEnrolling
类,而 BiometricsEnrollEnrolling
类实现了 BiometricEnrollSidecar.Listener
接口,所以 FingerprintEnrollEnrolling
也实现了 BiometricEnrollSidecar.Listener
接口。
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
/**
* Activity which handles the actual enrolling for fingerprint.
*/
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
// 指纹录制时提示(比如太快,移动手指之类)
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
if (!TextUtils.isEmpty(helpString)) {
mErrorText.removeCallbacks(mTouchAgainRunnable);
showError(helpString);
}
}
// 提示指纹录制过程中超时,或者未注册
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
int msgId;
switch (errMsgId) {
case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
msgId = R.string.security_settings_fingerprint_enroll_error_timeout_dialog_message;
break;
default:
msgId = R.string.security_settings_fingerprint_enroll_error_generic_dialog_message;
break;
}
showErrorDialog(getText(msgId), errMsgId);
stopIconAnimation();
mErrorText.removeCallbacks(mTouchAgainRunnable);
}
// 录制过程中进度的变化(手指按压指纹传感区,onEnrollmentProgressChange() 会被触发,执行一系列处理工作)
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */); // 更新进度
updateDescription(); // 更新描述
clearError();
animateFlash(); // 更新动画
mErrorText.removeCallbacks(mTouchAgainRunnable);
mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
}
}
// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
implements BiometricEnrollSidecar.Listener {
@Override
protected void onStart() {
super.onStart();
if (shouldStartAutomatically()) { // 恒定为 true
startEnrollment(); // 调用 startEnrollment() 方法
}
}
}
// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
implements BiometricEnrollSidecar.Listener {
protected BiometricEnrollSidecar mSidecar;
protected abstract BiometricEnrollSidecar getSidecar(); // 抽象方法,由子类实现
public void startEnrollment() {
// 调用 BiometricEnrollSidecar 的 onStart() 方法
mSidecar = (BiometricEnrollSidecar) getSupportFragmentManager()
.findFragmentByTag(TAG_SIDECAR);
if (mSidecar == null) {
mSidecar = getSidecar(); // 获取 mSidecar
getSupportFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR)
.commitAllowingStateLoss();
}
mSidecar.setListener(this);
}
}
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected BiometricEnrollSidecar getSidecar() {
// 返回了一个继承自 BiometricEnrollSidecar 的 FingerprintEnrollSidecar 对象
return new FingerprintEnrollSidecar();
}
}
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
/**
* Sidecar fragment to handle the state around fingerprint enrollment.
*/
public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
private FingerprintManager mFingerprintManager;
@Override
protected void startEnrollment() {
super.startEnrollment();
if (mUserId != UserHandle.USER_NULL) {
mFingerprintManager.setActiveUser(mUserId);
}
/*
* 调用 FingeprintManager 的 enroll() 方法开始录入,并且传入了 EnrollmentCallback 对象
* EnrollmentCallback 是指纹录入结果的回调,分别调用了 BiometricEnrollSidecar.Listener 接口中的方法,
* 这样就能更新指纹录制的进度和录制结果。
*/
mFingerprintManager.enroll(mToken, mEnrollmentCancel, 0 /* flags */, mUserId, mEnrollmentCallback);
}
我们看下 EnrollmentCallback
对象是什么:
// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
private FingerprintManager.EnrollmentCallback mEnrollmentCallback
= new FingerprintManager.EnrollmentCallback() {
@Override
public void onEnrollmentProgress(int remaining) {
FingerprintEnrollSidecar.super.onEnrollmentProgress(remaining);
}
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
}
};
}
// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java
public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
private IFingerprintService mService;
// CancellationSignal 类提供删除信号类,提供终止操作的能力
@RequiresPermission(MANAGE_FINGERPRINT)
public void enroll(byte [] token, CancellationSignal cancel, int flags,
int userId, EnrollmentCallback callback) {
if (userId == UserHandle.USER_CURRENT) {
userId = getCurrentUserId();
}
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Slog.w(TAG, "enrollment already canceled");
return;
} else {
cancel.setOnCancelListener(new OnEnrollCancelListener());
}
}
if (mService != null) try {
mEnrollmentCallback = callback;
// 调用 FingerprintServiceWrapper 的 enroll() 方法
mService.enroll(mToken, token, userId, mServiceReceiver, flags,
mContext.getOpPackageName());
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
if (callback != null) {
// Though this may not be a hardware issue, it will cause apps to give up or try
// again later.
callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */));
}
}
}
}
FingerprintManager
与 FingerprintService
直接通过 aidl
进行通信,在 FingerprintService
中内部类 FingerprintServiceWrapper
实现了 IFingerprintService.Stub
,我们调用的 FingerManger
的 enroll()
方法就是调用 FingerprintServiceWrapper
类中的 enroll()
方法。
// frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
public class FingerprintService extends BiometricServiceBase {
/**
* Receives the incoming binder calls from FingerprintManager.
*/
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
@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 boolean restricted = isRestricted();
final int groupId = userId; // default group for fingerprint enrollment
final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId,
cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */,
ENROLL_TIMEOUT_SEC) {
@Override
public boolean shouldVibrate() {
return true;
}
@Override
protected int statsModality() {
return FingerprintService.this.statsModality();
}
};
enrollInternal(client, userId); // 调用 BiometricServiceBase 的 enrollInternal() 方法
}
}
}
// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
public abstract class BiometricServiceBase extends SystemService
implements IHwBinder.DeathRecipient {
protected void enrollInternal(EnrollClientImpl client, int userId) {
if (hasReachedEnrollmentLimit(userId)) {
return;
}
// Group ID is arbitrarily set to parent profile user ID. It just represents
// the default biometrics for the user.
if (!isCurrentUserOrProfile(userId)) {
return;
}
mHandler.post(() -> {
startClient(client, true /* initiatedByClient */); // 调用 startClient() 方法
});
}
}
// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
public abstract class BiometricServiceBase extends SystemService
implements IHwBinder.DeathRecipient {
private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
ClientMonitor currentClient = mCurrentClient;
if (currentClient != null) {
if (DEBUG) Slog.v(getTag(), "request stop current client " +
currentClient.getOwnerString());
if (currentClient instanceof InternalEnumerateClient
|| currentClient instanceof InternalRemovalClient) {
if (newClient != null) {
Slog.w(getTag(), "Internal cleanup in progress but trying to start client "
+ newClient.getClass().getSuperclass().getSimpleName()
+ "(" + newClient.getOwnerString() + ")"
+ ", initiatedByClient = " + initiatedByClient);
}
} else {
currentClient.stop(initiatedByClient);
mHandler.removeCallbacks(mResetClientState);
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
}
mPendingClient = newClient;
} else if (newClient != null) {
if (newClient instanceof AuthenticationClient) {
AuthenticationClient client = (AuthenticationClient) newClient;
if (client.isBiometricPrompt()) {
if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie());
mCurrentClient = newClient;
if (mBiometricService == null) {
mBiometricService = IBiometricService.Stub.asInterface(
ServiceManager.getService(Context.BIOMETRIC_SERVICE));
}
try {
mBiometricService.onReadyForAuthentication(client.getCookie(),
client.getRequireConfirmation(), client.getTargetUserId());
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception", e);
}
return;
}
}
// We are not a BiometricPrompt client, start the client immediately
mCurrentClient = newClient;
startCurrentClient(mCurrentClient.getCookie()); // 调用 startCurrentClient() 方法
}
}
}
// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
public abstract class BiometricServiceBase extends SystemService
implements IHwBinder.DeathRecipient {
private ClientMonitor mCurrentClient;
protected void startCurrentClient(int cookie) {
if (mCurrentClient == null) {
Slog.e(getTag(), "Trying to start null client!");
return;
}
if (DEBUG) Slog.v(getTag(), "starting client "
+ mCurrentClient.getClass().getSuperclass().getSimpleName()
+ "(" + mCurrentClient.getOwnerString() + ")"
+ " targetUserId: " + mCurrentClient.getTargetUserId()
+ " currentUserId: " + mCurrentUserId
+ " cookie: " + cookie + "/" + mCurrentClient.getCookie());
if (cookie != mCurrentClient.getCookie()) {
Slog.e(getTag(), "Mismatched cookie");
return;
}
notifyClientActiveCallbacks(true);
mCurrentClient.start(); // 调用 EnrollClient 的 start() 方法
}
}
// frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java
// EnrollClient 是为给定的客户端跟踪指纹录制状态
public abstract class EnrollClient extends ClientMonitor {
// start 方法会调用 fingerprintd,调用底层的指纹库,底层库返回结果后会调用 onEnrollResult 来反馈结果给 receiver,再往上层反馈。
@Override
public int start() {
mEnrollmentStartTimeMs = System.currentTimeMillis();
try {
final ArrayList<Integer> disabledFeatures = new ArrayList<>();
for (int i = 0; i < mDisabledFeatures.length; i++) {
disabledFeatures.add(mDisabledFeatures[i]);
}
final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), mTimeoutSec,
disabledFeatures);
if (result != 0) {
Slog.w(getLogTag(), "startEnroll failed, result=" + result);
mMetricsLogger.histogram(mConstants.tagEnrollStartError(), result);
onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */);
return result;
}
} catch (RemoteException e) {
Slog.e(getLogTag(), "startEnroll failed", e);
}
return 0; // success
}
}
getDaemonWrapper().enroll()
会调用 fingerprintd
,调用底层的指纹库,底层库返回结果后会调用 onEnrollResult
来反馈结果给 receiver
,在往上层反馈。这就是指纹的录制流程。
// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java
public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
private Handler mHandler;
// mServiceReceiver 对象会通过 handler 发送相关消息去调用 EnrollmentCallback 或者 AuthenticationCallback 中方法
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
@Override // binder call
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
@Override // binder call
public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode,
deviceId).sendToTarget();
}
@Override // binder call
public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
}
@Override // binder call
public void onAuthenticationFailed(long deviceId) {
mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
}
@Override // binder call
public void onError(long deviceId, int error, int vendorCode) {
mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
}
@Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
@Override // binder call
public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
// TODO: propagate remaining
mHandler.obtainMessage(MSG_ENUMERATED, fingerId, groupId, deviceId).sendToTarget();
}
};
private class MyHandler extends Handler {
private MyHandler(Context context) {
super(context.getMainLooper());
}
private MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_ENROLL_RESULT:
sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
break;
case MSG_ACQUIRED:
sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */,
msg.arg2 /* vendorCode */);
break;
case MSG_AUTHENTICATION_SUCCEEDED:
sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
break;
case MSG_AUTHENTICATION_FAILED:
sendAuthenticatedFailed();
break;
case MSG_ERROR:
sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */,
msg.arg2 /* vendorCode */);
break;
case MSG_REMOVED:
sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
break;
case MSG_ENUMERATED:
sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
msg.arg2 /* groupId */);
break;
}
}
};
}
看下 MSG_ENROLL_RESULT
:
// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.java
public class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {
private void sendEnrollResult(Fingerprint fp, int remaining) {
if (mEnrollmentCallback != null) {
// 调用 EnrollmentCallback 的 onEnrollmentProgress 方法
mEnrollmentCallback.onEnrollmentProgress(remaining);
}
}
}