指纹录制的activity为FingerprintEnrollEnrolling实现了FingerprintEnrollSidecar.Listener 接口。
//指纹录制时提示(比如太快,移动手指之类)
@Override
public void onEnrollmentHelp(CharSequence helpString) {
mErrorText.setText(helpString);
}
//提示指纹录制过程中超时,或者未注册。
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
int msgId;
......
showErrorDialog(getText(msgId), errMsgId);
......
}
//录制过程中进度的变化
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */);//更新进度
updateDescription();//更新描述
animateFlash();//更新动画
......
}
FingerprintEnrollSidecar的onStart方法中调用了startEnrollment(),该方法中调用FingeprintManager的enroll方法,并且传入了EnrollmentCallback对象,EnrollmentCallback是指纹录入结果的回调,分别调用了FingerprintEnrollSidecar.Listener 接口中的方法,这样就能更新指纹录制的进度和录制结果。
private void startEnrollment() {
......
mFingerprintManager.enroll(mToken, mEnrollmentCancel,
0 /* flags */, mUserId, mEnrollmentCallback);
mEnrolling = true;
}
private FingerprintManager.EnrollmentCallback mEnrollmentCallback
= new FingerprintManager.EnrollmentCallback() {
@Override
public void onEnrollmentProgress(int remaining) {
......
mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
}
}
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
if (mListener != null) {
mListener.onEnrollmentHelp(helpString);
}
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
if (mListener != null) {
mListener.onEnrollmentError(errMsgId, errString);
}
mEnrolling = false;
}
};
public void enroll(byte [] token, CancellationSignal cancel, int flags,
int userId, EnrollmentCallback callback) {
......
mService.enroll(mToken, token, userId, mServiceReceiver, flags,
mContext.getOpPackageName());
......
注意传入的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) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, 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) {
mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
}
@Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId) {
mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
}
};
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 */);
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 */);
break;
case MSG_REMOVED:
sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
msg.arg2 /* groupId */);
}
}
FingerprintManager与FingerprintService直接通过aidl进行通信,在FingerprintService中内部类FingerprintServiceWrapper实现了IFingerprintService.Stub,我们调用的FingerManger的enroll方法就是调用FingerprintServiceWrapper类中的enroll()。
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 int limit = mContext.getResources().getInteger(
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
final int enrolled = FingerprintService.this.
getEnrolledFingerprints(userId).size();
if (enrolled >= limit) {
Slog.w(TAG, "Too many fingerprints registered");
return;
}
......
mHandler.post(new Runnable() {
@Override
public void run() {
startEnrollment(token, cryptoToken, userId, receiver,
flags,restricted, opPackageName);
}
});
}
startEnrollment方法中会调用EnrollClient的start方法,EnrollClient是为给定的客户端跟踪指纹录制状态。
/**
* A class to keep track of the enrollment state for a given client.
*/
public abstract class EnrollClient extends ClientMonitor {
......
public EnrollClient(Context context, long halDeviceId, IBinder token,
IFingerprintServiceReceiver receiver, int userId, int groupId, byte [] cryptoToken,
boolean restricted, String owner) {
super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
......
}
@Override
public boolean onEnrollResult(int fingerId, int groupId, int remaining) {
......
return sendEnrollResult(fingerId, groupId, remaining);
}
/*
* @return true if we're done.
*/
private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
IFingerprintServiceReceiver receiver = getReceiver();
......
receiver.onEnrollResult(getHalDeviceId(), fpId, groupId, remaining);
......
}
@Override
public int start() {
IFingerprintDaemon daemon = getFingerprintDaemon();
......
final int result = daemon.enroll(mCryptoToken, getGroupId(), timeout);
......
return 0; // success
}
start方法会调用fingerprintd,调用底层的指纹库,底层库返回结果后会调用onEnrollResult来反馈结果给receiver,在往上层反馈。这就是指纹的录制流程。