共计 22788 个字符,预计需要花费 57 分钟才能阅读完成。
前言
因为源码剖析的代码量比拟大,大部分博客网站的内容显示页面都比拟窄,显示进去的成果都异样俊俏,所以您也能够间接查看《Thinking in Android》来浏览这边文章,心愿这篇文章能帮你梳理分明 “指纹注册流程”。
外围源码
要害类 | 门路 |
---|---|
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.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
中解决。
二、BiometricEnrollIntroduction
2.1 BiometricEnrollIntroduction.onNextButtonClick()
// 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();} | |
} | |
} |
2.2 BiometricEnrollIntroduction.launchNextEnrollingActivity()
// 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 | |
} | |
} |
三、FingerprintEnrollFindSensor
咱们把下面的图再拿过去,此时就进入了图 2 界面的逻辑,咱们接着往下看。
3.1 FingerprintEnrollFindSensor.onCreate()
// 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 界面的相干逻辑,接下来的代码逻辑就略微简单一点了,咱们认真深挖钻研。
3.2 FingerprintEnrollFindSensor.startLookingForFingerprint()
// 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
界面。
四、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 { | |
@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); | |
} | |
} |
五、BiometricsEnrollEnrolling
5.1 BiometricsEnrollEnrolling.onStart()
// 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() 办法 | |
} | |
} | |
} |
5.2 BiometricsEnrollEnrolling.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();} | |
} |
六、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; | |
@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); | |
} | |
}; | |
} |
七、FingerprintManager
7.1 FingerprintManager.enroll()
// 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 */)); | |
} | |
} | |
} | |
} |
八、FingerprintService
8.1 FingerprintServiceWrapper.enroll()
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() 办法} | |
} | |
} |
九、BiometricServiceBase
9.1 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() 办法}); | |
} | |
} |
9.2 BiometricServiceBase.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() 办法} | |
} | |
} |
9.3 BiometricServiceBase.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() 办法 | |
} | |
} |
十、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,再往下层反馈。@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); | |
} | |
} | |
} |