# 前言

由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 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 图,这个你应该不陌生了。

一、FingerprintEnrollIntroduction

接下来我们就从指纹引导界面开始源码分析,图 1 的逻辑就在 FingerprintEnrollIntroduction 类,点击 Next 执行下一步,会执行 onNextButtonClick() 方法。

1.1 FingerprintEnrollIntroduction.onNextButtonClick()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.javapublic class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mFingerprintManager = Utils.getFingerprintManagerOrNull(this);mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);// Cancel ButtonmFooterBarMixin.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 ButtonmFooterBarMixin.setPrimaryButton(new FooterButton.Builder(this).setText(R.string.wizard_next).setListener(this::onNextButtonClick)    // 点击 "下一步" 的处理流程.setButtonType(FooterButton.ButtonType.NEXT).setTheme(R.style.SudGlifButton_Primary).build());}}

我们可以发现:FingerprintEnrollIntroduction 继承自 BiometricEnrollIntroductiononNextButtonClick() 方法在其父类 BiometricEnrollIntroduction 中处理。

二、BiometricEnrollIntroduction

2.1 BiometricEnrollIntroduction.onNextButtonClick()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.javapublic abstract class BiometricEnrollIntroduction extends BiometricEnrollBaseimplements LinkSpan.OnClickListener {@Overrideprotected void onNextButtonClick(View view) {mNextClicked = true;if (checkMaxEnrolled() == 0) {// Lock thingy is already set up, launch directly to the next pagelaunchNextEnrollingActivity(mToken);    // 接下来就要拉起指纹录入界面} else {setResult(RESULT_FINISHED);finish();}}}

2.2 BiometricEnrollIntroduction.launchNextEnrollingActivity()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollIntroduction.javapublic abstract class BiometricEnrollIntroduction extends BiometricEnrollBaseimplements LinkSpan.OnClickListener {private void launchNextEnrollingActivity(byte[] token) {Intent intent = getEnrollingIntent();    // 获取 FingerprintEnrollFindSensorif (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.javapublic abstract class BiometricEnrollIntroduction extends BiometricEnrollBaseimplements LinkSpan.OnClickListener {protected abstract Intent getEnrollingIntent();    // 抽象方法,由子类 FingerprintEnrollIntroduction 实现}

所以我们跳转到 FingerprintEnrollIntroduction

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.javapublic class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {@Overrideprotected Intent getEnrollingIntent() {return new Intent(this, FingerprintEnrollFindSensor.class);    // 获取 FingerprintEnrollFindSensor}}

三、FingerprintEnrollFindSensor

我们把上面的图再拿过来,此时就进入了图 2 界面的逻辑,我们接着往下看。

3.1 FingerprintEnrollFindSensor.onCreate()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.javapublic class FingerprintEnrollFindSensor extends BiometricEnrollBase {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(getContentView());mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);// Skip buttonmFooterBarMixin.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 sensorsetHeaderText(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 界面的相关逻辑,接下来的代码逻辑就稍微复杂一点了,我们仔细深挖研究。

3.2 FingerprintEnrollFindSensor.startLookingForFingerprint()

// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.javapublic 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();// 添加 FingerprintEnrollEnrollinggetSupportFragmentManager().beginTransaction().add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR).commitAllowingStateLoss();}// FingerprintEnrollEnrolling 实现了 BiometricEnrollSidecar.Listener 接口mSidecar.setListener(new Listener() {    // 匿名内部类的方式实现接口方法@Overridepublic void onEnrollmentProgressChange(int steps, int remaining) {mNextClicked = true;proceedToEnrolling(true /* cancelEnrollment */);}@Overridepublic void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {}@Overridepublic 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.javapublic 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 的 IntentstartActivityForResult(getFingerprintEnrollingIntent(), ENROLL_REQUEST);}}}

正常流程会走到 startActivityForResult() 方法,跳转到 FingerprintEnrollEnrolling 界面。

四、FingerprintEnrollEnrolling

我们把上面的图再拿过来,此时就进入了图 3 界面的逻辑,我们接着往下看。

4.1 FingerprintEnrollEnrolling.onStart()

我们重点关注 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 {@Overrideprotected 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 {// 指纹录制时提示(比如太快,移动手指之类)@Overridepublic void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {if (!TextUtils.isEmpty(helpString)) {mErrorText.removeCallbacks(mTouchAgainRunnable);showError(helpString);}}// 提示指纹录制过程中超时,或者未注册@Overridepublic 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() 会被触发,执行一系列处理工作)@Overridepublic void onEnrollmentProgressChange(int steps, int remaining) {updateProgress(true /* animate */);    // 更新进度updateDescription();    // 更新描述clearError();animateFlash();    // 更新动画mErrorText.removeCallbacks(mTouchAgainRunnable);mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);}}

五、BiometricsEnrollEnrolling

5.1 BiometricsEnrollEnrolling.onStart()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.javapublic abstract class BiometricsEnrollEnrolling extends BiometricEnrollBaseimplements BiometricEnrollSidecar.Listener {@Overrideprotected void onStart() {super.onStart();if (shouldStartAutomatically()) {    // 恒定为 truestartEnrollment();    // 调用 startEnrollment() 方法}}}

5.2 BiometricsEnrollEnrolling.startEnrollment()

// packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.javapublic abstract class BiometricsEnrollEnrolling extends BiometricEnrollBaseimplements 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();    // 获取 mSidecargetSupportFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR).commitAllowingStateLoss();}mSidecar.setListener(this);}}// packages/apps/Settings/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.javapublic class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {@Overrideprotected BiometricEnrollSidecar getSidecar() {// 返回了一个继承自 BiometricEnrollSidecar 的 FingerprintEnrollSidecar 对象return new FingerprintEnrollSidecar();}}

六、FingerprintEnrollSidecar

6.1 FingerprintEnrollSidecar.startEnrollment()

// 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;@Overrideprotected 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.javapublic class FingerprintEnrollSidecar extends BiometricEnrollSidecar {private FingerprintManager.EnrollmentCallback mEnrollmentCallback= new FingerprintManager.EnrollmentCallback() {@Overridepublic void onEnrollmentProgress(int remaining) {FingerprintEnrollSidecar.super.onEnrollmentProgress(remaining);}@Overridepublic void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);}@Overridepublic void onEnrollmentError(int errMsgId, CharSequence errString) {FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);}};}

七、FingerprintManager

7.1 FingerprintManager.enroll()

// frameworks/base/core/java/android/hardware/fingerprint/FingerprintManager.javapublic 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 */));}}}}

八、FingerprintService

8.1 FingerprintServiceWrapper.enroll()

FingerprintManagerFingerprintService 直接通过 aidl 进行通信,在 FingerprintService 中内部类 FingerprintServiceWrapper 实现了 IFingerprintService.Stub,我们调用的 FingerMangerenroll() 方法就是调用 FingerprintServiceWrapper 类中的 enroll() 方法。

// frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.javapublic class FingerprintService extends BiometricServiceBase {/*** Receives the incoming binder calls from FingerprintManager.*/private final class FingerprintServiceWrapper extends IFingerprintService.Stub {@Override // Binder callpublic 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 enrollmentfinal EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId,cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */,ENROLL_TIMEOUT_SEC) {@Overridepublic boolean shouldVibrate() {return true;}@Overrideprotected int statsModality() {return FingerprintService.this.statsModality();}};enrollInternal(client, userId);    // 调用 BiometricServiceBase 的 enrollInternal() 方法}}}

九、BiometricServiceBase

9.1 BiometricServiceBase.enrollInternal()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.javapublic abstract class BiometricServiceBase extends SystemServiceimplements 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() 方法});}      }

9.2 BiometricServiceBase.startClient()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.javapublic abstract class BiometricServiceBase extends SystemServiceimplements 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 immediatelymCurrentClient = newClient;startCurrentClient(mCurrentClient.getCookie());    // 调用 startCurrentClient() 方法}}}

9.3 BiometricServiceBase.startCurrentClient()

// frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.javapublic abstract class BiometricServiceBase extends SystemServiceimplements 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() 方法}}

十、EnrollClient

10.1 EnrollClient.start()

// frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java// EnrollClient 是为给定的客户端跟踪指纹录制状态
public abstract class EnrollClient extends ClientMonitor {// start 方法会调用 fingerprintd,调用底层的指纹库,底层库返回结果后会调用 onEnrollResult 来反馈结果给 receiver,再往上层反馈。@Overridepublic 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.javapublic class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {private Handler mHandler;// mServiceReceiver 对象会通过 handler 发送相关消息去调用 EnrollmentCallback 或者 AuthenticationCallback 中方法private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {@Override // binder callpublic 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 callpublic void onAcquired(long deviceId, int acquireInfo, int vendorCode) {mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode,deviceId).sendToTarget();}@Override // binder callpublic void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();}@Override // binder callpublic void onAuthenticationFailed(long deviceId) {mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();}@Override // binder callpublic void onError(long deviceId, int error, int vendorCode) {mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();}@Override // binder callpublic 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 callpublic void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {// TODO: propagate remainingmHandler.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);}@Overridepublic 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.javapublic class FingerprintManager implements BiometricAuthenticator, BiometricFingerprintConstants {private void sendEnrollResult(Fingerprint fp, int remaining) {if (mEnrollmentCallback != null) {// 调用 EnrollmentCallback 的 onEnrollmentProgress 方法mEnrollmentCallback.onEnrollmentProgress(remaining);}}}

# Enroll 流程图

【 Android 10 生物识别 】系列 -- Fingerprint_指纹录入流程相关推荐

  1. 【 Android 10 系统启动 】系列 -- ShutdownThread(关机流程)

    # 前言 由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 < Thinking in Android > 来阅读这边文章, ...

  2. 生物解锁--指纹录入流程

    直接从FingerprintManager.java类开始讲起. 首先从enroll方法作为入口 /*** Request fingerprint enrollment. This call warm ...

  3. android懒加载单实例,【 Android 10 设计模式 】系列 -- 单例

    前言 由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 < Thinking in Android > 来阅读这边文章,希望 ...

  4. android launcher目录,【 Android 10 系统启动 】系列 -- Launcher(应用门户)

    前言 由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 < Thinking in Android > 来阅读这边文章,希望 ...

  5. 【Android 10 源码】Camera v1 startPreview 流程

    Camera v1 startPreview 起点位于 android.hardware 包下的 Camera 类中,这是老版本的 Camera 预览的起点. 上面这张相机架构图左边就是关于 Came ...

  6. 优麒麟 mysql_优麒麟18.10新特性预览—生物识别

    随着优麒麟18.10正式发布的日子越来越近,小编又给大家带来了一个激动人心的功能.我们知道现在越来越多的电脑都带有指纹解锁的功能,但是我们的各大linux发行版却不支持,我们广大linuxer怎么能容 ...

  7. linux kylin使用手册,优麒麟Ubuntu Kylin 18.10中的生物识别管理工具,附使用方法

    优麒麟Ubuntu Kylin 18.10有一个生物识别管理工具,可对生物特征管理.当前越来越多的电脑都搭载有指纹解锁的功能,Ubuntu Kylin 18.10增加了生物识别的支持,下面我们一起来看 ...

  8. NEC为印度Aadhaar项目提供的生物识别系统注册人数突破10亿

    由NEC提供生物识别系统.印度国民ID管理局(简称UIDAI)主导进行并可为每位国民签发独有身份ID的Aadhaar项目,截至2016年4月其注册人数已经突破10亿.NEC通过提供集指纹 面部 虹膜等 ...

  9. 人脸识别与膜虹识别_指纹,人脸,虹膜三种生物识别优缺点比较

    就生物识别本身来说,也可以分为指纹识别.人脸识别.虹膜识别.掌/指纹静脉识别等.各种识别方式因各自特性适用于不同的领域.下面将其中应用最广泛的三种识别进行比较介绍. 指纹识别:便捷易操作,但存在被复制 ...

  10. 生物识别:怎样才能把想象力转化成商机

    新模式.新市场.新技术尚待时间检验 生物识别,一种既熟悉又神秘的高科技.人们常常在电影中看到关于生物识别一系列眼花缭乱的应用:例如用虹膜识别进入金库.用指纹识别进入实验室,或是用语音识别向家中的机器人 ...

最新文章

  1. 阿里开源项目汇总(二十)
  2. 商城网站该如何选择虚拟主机
  3. UVa 10570 - Meeting with Aliens
  4. bzoj4171: Rhl的游戏
  5. 网络请求 get 请求时, 如果参数中的字符带有+号
  6. 踢向《英雄王座》的面目全非脚
  7. [kuangbin带你飞]专题一 简单搜索 - H - Pots
  8. matlab read grads,讲解:Grads Only、Network、Matlab、MatlabProcessing|P
  9. php url 转码,php url中文转码的方法
  10. python3超简代码爬取桌面壁纸
  11. PMP备考大全:经典题库(8月第4周)
  12. 《小话投行》转自2011 Morgan Stanley HK IBD唯一的大陆本科生
  13. Docker (四) 容器基本命令
  14. 作为一名IT工程师该如何提前预防职业病
  15. DragonEnglish——COCA20000单词+音频+释义+例句及翻译内容聚合
  16. 在线教育平台项目——整体架构
  17. 超详解The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone
  18. java开源自定义表单_java开发自定义表单功能类:FormUtil
  19. 珠峰登顶在即,5G如何先行?
  20. #Python3小练习,随缘更新

热门文章

  1. k8s集群外部域名dns解析问题
  2. 绿巨人(Hulk - Pure CSS)
  3. 阿里云域名购买和域名解析教程
  4. 毕业设计论文-基于matlab的车牌识别系统
  5. 计算机硬盘应该什么格式化,磁盘格式化是什么意思?快速格式化和一般格式化有什么区别...
  6. Java11新特性及代码示例
  7. buuctf——(HDCTF2019)Maze
  8. vb.net 简单取摄像头图片_简单的BP网络识别液晶字符
  9. 小学数学题生成器java_JAVA小学四则运算生成器(聂适涵,邱品)
  10. 性能测试工具篇(开源商业)