现代智能手机,基本上都有人脸解锁功能,那他是怎么实现的哦?下面从代码角度来分析下他。
先上流程图
略
人脸解锁,都要先录入(这部分后面会出其他博客),再注册,再人脸解锁,响应,下面从代码角度来分析他。
先从锁屏部分的类KeyguardUpdateMonitor入手,下面是人脸服务注册方法。
private void startListeningForFace() {
final int userId = getCurrentUser();
final boolean unlockPossible = isUnlockWithFacePossible(userId);
if (mFaceCancelSignal != null) {
Log.e(TAG, "Cancellation signal is not null, high chance of bug in face auth lifecycle"
+ " management. Face state: " + mFaceRunningState
+ ", unlockPossible: " + unlockPossible);
}
if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
return;
} else if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
// Waiting for ERROR_CANCELED before requesting auth again
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFace(): " + mFaceRunningState);
if (unlockPossible) {
mFaceCancelSignal = new CancellationSignal();
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
mFaceAuthUserId = userId;
if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else {
final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
mFaceAuthenticationCallback, null /* handler */, userId, isBypassEnabled);
}
setFaceRunningState(BIOMETRIC_STATE_RUNNING);
}
}
第31行,人脸注册,这里要注意下变量mFaceAuthenticationCallback,这是回调接口对象,底层设别结果的回传信息,会通过这个变量对象告知用户人脸解锁成功或失败或错误,等等。
@VisibleForTesting
final FaceManager.AuthenticationCallback mFaceAuthenticationCallback
= new FaceManager.AuthenticationCallback() {
@Override
public void onAuthenticationFailed() {
handleFaceAuthFailed();
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
}
}
@Override
public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
Trace.endSection();
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
}
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFaceHelp(helpMsgId, helpString.toString());
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFaceError(errMsgId, errString.toString());
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
}
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFaceAcquired(acquireInfo);
}
};
后面在设别结果回传的时候,再讨论。
回到代码mFaceManager#authenticate 部分,讨论下变量mFaceManager是如何定义的。
在KeyguardUpdateMonitor类的构造函数中定义的,如下,显然这是一个系统服务。
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
mFaceManager = (FaceManager) context.getSystemService(Context.FACE_SERVICE);
mFaceSensorProperties = mFaceManager.getSensorPropertiesInternal();
}
搜索关键字Context.FACE_SERVICE,在SystemServiceRegistry类中实现了系统服务注册。
registerService(Context.FACE_SERVICE, FaceManager.class,
new CachedServiceFetcher<FaceManager>() {
@Override
public FaceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
final IBinder binder;
if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
binder = ServiceManager.getServiceOrThrow(Context.FACE_SERVICE);
} else {
binder = ServiceManager.getService(Context.FACE_SERVICE);
}
IFaceService service = IFaceService.Stub.asInterface(binder);
return new FaceManager(ctx.getOuterContext(), service);
}
});
注意第12,13行,会获得跨进程对象FaceService对象实例,然后绑定到FaceManager系统对象实例中,然后在mFaceManager#authenticate方法中,使用mService 变量,调用到FaceService对象实例下的authenticate方法。
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId,
boolean isKeyguardBypassEnabled) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null && cancel.isCanceled()) {
Slog.w(TAG, "authentication already canceled");
return;
}
if (mService != null) {
try {
useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
final long authId = mService.authenticate(mToken, operationId, userId,
mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception while authenticating: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or
// try again later.
callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE,
getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */));
} finally {
Trace.endSection();
}
}
}
搜索IFaceService service = IFaceService.Stub.asInterface(binder);
可以判断出mService 就是跨进程对象实例FaceService
第22行,注意mServiceReceiver,这是一个回调接口对象,应该是跨进程的,后面会讲到。
来到FaceService#authenticate
@Override // Binder call
public long authenticate(final IBinder token, final long operationId, int userId,
final IFaceServiceReceiver receiver, final String opPackageName,
boolean isKeyguardBypassEnabled) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
// lockdown, something wrong happened. See similar path in FingerprintService.
final boolean restricted = false; // Face APIs are private
final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
? BiometricsProtoEnums.CLIENT_KEYGUARD
: BiometricsProtoEnums.CLIENT_UNKNOWN;
// Keyguard check must be done on the caller's binder identity, since it also checks
// permission.
final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return -1;
}
return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
0 /* cookie */,
new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
statsClient, isKeyguard, isKeyguardBypassEnabled);
}
第25行,provider.second,看看是什么对象。
先从第19行开始看起
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@Nullable
private Pair<Integer, ServiceProvider> getSingleProvider() {
final List<FaceSensorPropertiesInternal> properties = getSensorProperties();
if (properties.size() != 1) {
Slog.e(TAG, "Multiple sensors found: " + properties.size());
return null;
}
// Theoretically we can just return the first provider, but maybe this is easier to
// understand.
final int sensorId = properties.get(0).sensorId;
for (ServiceProvider provider : mServiceProviders) {
if (provider.containsSensor(sensorId)) {
return new Pair<>(sensorId, provider);
}
}
Slog.e(TAG, "Single sensor, but provider not found");
return null;
}
看看第12行的mServiceProviders集合变量在哪儿赋值的。
private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
mServiceProviders.add(
new Face10(getContext(), hidlSensor, mLockoutResetDispatcher));
}
}
从第4行代码,我们可以判断出provider.second 就是Face10对象实例。
provider.second.scheduleAuthenticate就是Face10对象实例下的scheduleAuthenticate方法。
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */, mSensorId,
isStrongBiometric, statsClient, mLockoutTracker, mUsageStats,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
mScheduler.scheduleClientMonitor(client);
});
}
第15行,看看变量mScheduler在哪儿定义的。
@VisibleForTesting
Face10(@NonNull Context context,
@NonNull FaceSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull BiometricScheduler scheduler) {
mSensorProperties = sensorProps;
mContext = context;
mSensorId = sensorProps.sensorId;
mScheduler = scheduler;
mHandler = new Handler(Looper.getMainLooper());
mUsageStats = new UsageStats(context);
mAuthenticatorIds = new HashMap<>();
mLazyDaemon = Face10.this::getDaemon;
mLockoutTracker = new LockoutHalImpl();
mHalResultController = new HalResultController(sensorProps.sensorId, context, mHandler,
mScheduler, mLockoutTracker, lockoutResetDispatcher);
mHalResultController.setCallback(() -> {
mDaemon = null;
mCurrentUserId = UserHandle.USER_NULL;
});
try {
ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to register user switch observer");
}
}
第9行,在Face10构造函数中赋值的,需要继续追踪,Face10对象实例在哪儿实现的,在
FaceService#addHidlProviders,会调用的,
private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
mServiceProviders.add(
new Face10(getContext(), hidlSensor, mLockoutResetDispatcher));
}
}
public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
this(context, sensorProps, lockoutResetDispatcher,
new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_FACE,
null /* gestureAvailabilityTracker */));
}
搜索前面的代码mScheduler.scheduleClientMonitor(client)
可以确定mScheduler 就是第4行的new BiometricScheduler对象实例。
那继续往下看mScheduler.scheduleClientMonitor(client),实际上就是
public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor) {
scheduleClientMonitor(clientMonitor, null /* clientFinishCallback */);
}
public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
@Nullable BaseClientMonitor.Callback clientCallback) {
// If the incoming operation should interrupt preceding clients, mark any interruptable
// pending clients as canceling. Once they reach the head of the queue, the scheduler will
// send ERROR_CANCELED and skip the operation.
if (clientMonitor.interruptsPrecedingClients()) {
for (Operation operation : mPendingOperations) {
if (operation.mClientMonitor instanceof Interruptable
&& operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "New client incoming, marking pending client as canceling: "
+ operation.mClientMonitor);
operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
}
}
}
mPendingOperations.add(new Operation(clientMonitor, clientCallback));
Slog.d(getTag(), "[Added] " + clientMonitor
+ ", new queue size: " + mPendingOperations.size());
// If the new operation should interrupt preceding clients, and if the current operation is
// cancellable, start the cancellation process.
if (clientMonitor.interruptsPrecedingClients()
&& mCurrentOperation != null
&& mCurrentOperation.mClientMonitor instanceof Interruptable
&& mCurrentOperation.mState == Operation.STATE_STARTED) {
Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
cancelInternal(mCurrentOperation);
}
startNextOperationIfIdle();
}
第31行,继续往下看
{
if (mCurrentOperation != null) {
Slog.v(getTag(), "Not idle, current operation: " + mCurrentOperation);
return;
}
if (mPendingOperations.isEmpty()) {
Slog.d(getTag(), "No operations, returning to idle");
return;
}
mCurrentOperation = mPendingOperations.poll();
final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;
Slog.d(getTag(), "[Polled] " + mCurrentOperation);
// If the operation at the front of the queue has been marked for cancellation, send
// ERROR_CANCELED. No need to start this client.
if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation);
if (!(currentClient instanceof Interruptable)) {
throw new IllegalStateException("Mis-implemented client or scheduler, "
+ "trying to cancel non-interruptable operation: " + mCurrentOperation);
}
final Interruptable interruptable = (Interruptable) currentClient;
interruptable.cancelWithoutStarting(getInternalCallback());
// Now we wait for the client to send its FinishCallback, which kicks off the next
// operation.
return;
}
if (mGestureAvailabilityDispatcher != null
&& mCurrentOperation.mClientMonitor instanceof AcquisitionClient) {
mGestureAvailabilityDispatcher.markSensorActive(
mCurrentOperation.mClientMonitor.getSensorId(),
true /* active */);
}
// Not all operations start immediately. BiometricPrompt waits for its operation
// to arrive at the head of the queue, before pinging it to start.
final boolean shouldStartNow = currentClient.getCookie() == 0;
if (shouldStartNow) {
if (mCurrentOperation.isUnstartableHalOperation()) {
final HalClientMonitor<?> halClientMonitor =
(HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
// Note down current length of queue
final int pendingOperationsLength = mPendingOperations.size();
final Operation lastOperation = mPendingOperations.peekLast();
Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
+ ". Last pending operation: " + lastOperation);
// For current operations, 1) unableToStart, which notifies the caller-side, then
// 2) notify operation's callback, to notify applicable system service that the
// operation failed.
halClientMonitor.unableToStart();
if (mCurrentOperation.mClientCallback != null) {
mCurrentOperation.mClientCallback.onClientFinished(
mCurrentOperation.mClientMonitor, false /* success */);
}
// Then for each operation currently in the pending queue at the time of this
// failure, do the same as above. Otherwise, it's possible that something like
// setActiveUser fails, but then authenticate (for the wrong user) is invoked.
for (int i = 0; i < pendingOperationsLength; i++) {
final Operation operation = mPendingOperations.pollFirst();
if (operation == null) {
Slog.e(getTag(), "Null operation, index: " + i
+ ", expected length: " + pendingOperationsLength);
break;
}
if (operation.isHalOperation()) {
((HalClientMonitor<?>) operation.mClientMonitor).unableToStart();
}
if (operation.mClientCallback != null) {
operation.mClientCallback.onClientFinished(operation.mClientMonitor,
false /* success */);
}
Slog.w(getTag(), "[Aborted Operation] " + operation);
}
// It's possible that during cleanup a new set of operations came in. We can try to
// run these. A single request from the manager layer to the service layer may
// actually be multiple operations (i.e. updateActiveUser + authenticate).
mCurrentOperation = null;
startNextOperationIfIdle();
} else {
Slog.d(getTag(), "[Starting] " + mCurrentOperation);
currentClient.start(getInternalCallback());
mCurrentOperation.mState = Operation.STATE_STARTED;
}
} else {
try {
mBiometricService.onReadyForAuthentication(currentClient.getCookie());
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
}
Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE;
}
}
第87行,变量currentClient是哪个对象
搜索前面的代码,发现下面2行代码
mCurrentOperation = mPendingOperations.poll();
final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor
继续搜索
mPendingOperations.add(new Operation(clientMonitor, clientCallback));
可以确定clientMonitor 我们需要的。
scheduleClientMonitor方法中,有变量clientMonitor,可以确定是传递过来的
就是FaceAuthenticationClient 对象实例。因此currentClient.start就是调用FaceAuthenticationClient下的start方法,另外注意下第87行的start下的参数,应该后面在分析回调的时候,会讨论到。现在来看FaceAuthenticationClient下的start方法。
@Override
public void start(@NonNull Callback callback) {
super.start(callback);
mState = STATE_STARTED;
}
第3行,继续追踪父类AuthenticationClient
/**
* Start authentication
*/
@Override
public void start(@NonNull Callback callback) {
super.start(callback);
final @LockoutTracker.LockoutMode int lockoutMode =
mLockoutTracker.getLockoutModeForUser(getTargetUserId());
if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
Slog.v(TAG, "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
int errorCode = lockoutMode == LockoutTracker.LOCKOUT_TIMED
? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
: BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
onError(errorCode, 0 /* vendorCode */);
return;
}
if (mTaskStackListener != null) {
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
}
Slog.d(TAG, "Requesting auth for " + getOwnerString());
mStartTimeMs = System.currentTimeMillis();
mAuthAttempted = true;
startHalOperation();
}
第27行,startHalOperation()最终调用的是FaceAuthenticationClient#startHalOperation()
@Override
protected void startHalOperation() {
try {
if (mSensorPrivacyManager != null
&& mSensorPrivacyManager
.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
getTargetUserId())) {
onError(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
} else {
mCancellationSignal = getFreshDaemon().authenticate(mOperationId);
}
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting auth", e);
onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
mCallback.onClientFinished(this, false /* success */);
}
}
第12行getFreshDaemon().authenticate(mOperationId);
getFreshDaemon()实际上是调用Face10#getFreshDaemon
private synchronized IBiometricsFace getDaemon() {
if (mTestHalEnabled) {
final TestHal testHal = new TestHal(mContext, mSensorId);
testHal.setCallback(mHalResultController);
return testHal;
}
if (mDaemon != null) {
return mDaemon;
}
Slog.d(TAG, "Daemon was null, reconnecting, current operation: "
+ mScheduler.getCurrentClient());
try {
mDaemon = IBiometricsFace.getService();
} catch (java.util.NoSuchElementException e) {
// Service doesn't exist or cannot be opened.
Slog.w(TAG, "NoSuchElementException", e);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to get face HAL", e);
}
if (mDaemon == null) {
Slog.w(TAG, "Face HAL not available");
return null;
}
mDaemon.asBinder().linkToDeath(this, 0 /* flags */);
// HAL ID for these HIDL versions are only used to determine if callbacks have been
// successfully set.
long halId = 0;
try {
halId = mDaemon.setCallback(mHalResultController).value;
} catch (RemoteException e) {
Slog.e(TAG, "Failed to set callback for face HAL", e);
mDaemon = null;
}
Slog.d(TAG, "Face HAL ready, HAL ID: " + halId);
if (halId != 0) {
scheduleLoadAuthenticatorIds();
scheduleInternalCleanup(ActivityManager.getCurrentUser(), null /* callback */);
scheduleGetFeature(mSensorId, new Binder(),
ActivityManager.getCurrentUser(),
BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, null,
mContext.getOpPackageName());
} else {
Slog.e(TAG, "Unable to set callback");
mDaemon = null;
}
return mDaemon;
}
第35行后面,是涉及到人脸设别后的结果回调相关。后面会介绍,现在继续第16行。是跨进程获取BiometricsFace.cpp对象实例。然后继续其BiometricsFace#authenticate方法。
Return<Status> BiometricsFace::authenticate(uint64_t /* operationId */) {
mClientCallback->onError(kDeviceId, mUserId, FaceError::HW_UNAVAILABLE, 0 /* vendorCode */);
return Status::OK;
}
现在,基本上人脸注册部分讲完了,继续往下说下设别结果如何回传的
搜索下,前面的代码mDaemon.setCallback(mHalResultController)
mHalResultController这是一个回调接口对象,设别结果从他往上回传。
mHalResultController = new HalResultController(sensorProps.sensorId, context, mHandler,
mScheduler, mLockoutTracker, lockoutResetDispatcher);
继续往下看这个类,实际上是个跨进程的回调接口对象
public static class HalResultController extends IBiometricsFaceClientCallback.Stub {
/**
* Interface to sends results to the HalResultController's owner.
*/
public interface Callback {
/**
* Invoked when the HAL sends ERROR_HW_UNAVAILABLE.
*/
void onHardwareUnavailable();
}
private final int mSensorId;
@NonNull private final Context mContext;
@NonNull private final Handler mHandler;
@NonNull private final BiometricScheduler mScheduler;
@Nullable private Callback mCallback;
@NonNull private final LockoutHalImpl mLockoutTracker;
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
HalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler,
@NonNull BiometricScheduler scheduler, @NonNull LockoutHalImpl lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
mSensorId = sensorId;
mContext = context;
mHandler = handler;
mScheduler = scheduler;
mLockoutTracker = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;
}
public void setCallback(@Nullable Callback callback) {
mCallback = callback;
}
@Override
public void onEnrollResult(long deviceId, int faceId, int userId, int remaining) {
mHandler.post(() -> {
final CharSequence name = FaceUtils.getLegacyInstance(mSensorId)
.getUniqueName(mContext, userId);
final Face face = new Face(name, faceId, deviceId);
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceEnrollClient)) {
Slog.e(TAG, "onEnrollResult for non-enroll client: "
+ Utils.getClientName(client));
return;
}
final FaceEnrollClient enrollClient = (FaceEnrollClient) client;
enrollClient.onEnrollResult(face, remaining);
});
}
@Override
public void onAuthenticated(long deviceId, int faceId, int userId,
ArrayList<Byte> token) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
return;
}
final AuthenticationConsumer authenticationConsumer =
(AuthenticationConsumer) client;
final boolean authenticated = faceId != 0;
final Face face = new Face("", faceId, deviceId);
authenticationConsumer.onAuthenticated(face, authenticated, token);
});
}
@Override
public void onAcquired(long deviceId, int userId, int acquiredInfo,
int vendorCode) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(TAG, "onAcquired for non-acquire client: "
+ Utils.getClientName(client));
return;
}
final AcquisitionClient<?> acquisitionClient =
(AcquisitionClient<?>) client;
acquisitionClient.onAcquired(acquiredInfo, vendorCode);
});
}
@Override
public void onError(long deviceId, int userId, int error, int vendorCode) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
+ ", client: " + (client != null ? client.getOwnerString() : null)
+ ", error: " + error
+ ", vendorCode: " + vendorCode);
if (!(client instanceof ErrorConsumer)) {
Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(
client));
return;
}
final ErrorConsumer errorConsumer = (ErrorConsumer) client;
errorConsumer.onError(error, vendorCode);
if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE");
if (mCallback != null) {
mCallback.onHardwareUnavailable();
}
}
});
}
@Override
public void onRemoved(long deviceId, ArrayList<Integer> removed, int userId) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(TAG, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
return;
}
final RemovalConsumer removalConsumer = (RemovalConsumer) client;
if (!removed.isEmpty()) {
// Convert to old fingerprint-like behavior, where remove() receives
// one removal at a time. This way, remove can share some more common code.
for (int i = 0; i < removed.size(); i++) {
final int id = removed.get(i);
final Face face = new Face("", id, deviceId);
final int remaining = removed.size() - i - 1;
Slog.d(TAG, "Removed, faceId: " + id + ", remaining: " + remaining);
removalConsumer.onRemoved(face, remaining);
}
} else {
removalConsumer.onRemoved(null, 0 /* remaining */);
}
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0, UserHandle.USER_CURRENT);
});
}
@Override
public void onEnumerate(long deviceId, ArrayList<Integer> faceIds, int userId) {
mHandler.post(() -> {
final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
+ Utils.getClientName(client));
return;
}
final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
if (!faceIds.isEmpty()) {
// Convert to old fingerprint-like behavior, where enumerate() receives one
// template at a time. This way, enumerate can share some more common code.
for (int i = 0; i < faceIds.size(); i++) {
final Face face = new Face("", faceIds.get(i), deviceId);
enumerateConsumer.onEnumerationResult(face, faceIds.size() - i - 1);
}
} else {
// For face, the HIDL contract is to receive an empty list when there are no
// templates enrolled. Send a null identifier since we don't consume them
// anywhere, and send remaining == 0 so this code can be shared with Face@1.1
enumerateConsumer.onEnumerationResult(null /* identifier */, 0);
}
});
}
@Override
public void onLockoutChanged(long duration) {
mHandler.post(() -> {
Slog.d(TAG, "onLockoutChanged: " + duration);
final @LockoutTracker.LockoutMode int lockoutMode;
if (duration == 0) {
lockoutMode = LockoutTracker.LOCKOUT_NONE;
} else if (duration == -1 || duration == Long.MAX_VALUE) {
lockoutMode = LockoutTracker.LOCKOUT_PERMANENT;
} else {
lockoutMode = LockoutTracker.LOCKOUT_TIMED;
}
mLockoutTracker.setCurrentUserLockoutMode(lockoutMode);
if (duration == 0) {
mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorId);
}
});
}
}
第55和69行,设别结果回传到这里。
搜索mScheduler.scheduleClientMonitor(client)。
最终能确定第69行的client就是FaceAuthenticationClient对象实例
然后调用其下的onAuthenticated方法,回传到这里
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
mState = STATE_STOPPED;
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
authenticated,
0 /* error */,
0 /* vendorError */,
getTargetUserId()));
}
第4行,看其父类的方法
@Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> hardwareAuthToken) {
super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
getTargetUserId(), isBiometricPrompt());
final ClientMonitorCallbackConverter listener = getListener();
if (DEBUG) Slog.v(TAG, "onAuthenticated(" + authenticated + ")"
+ ", ID:" + identifier.getBiometricId()
+ ", Owner: " + getOwnerString()
+ ", isBP: " + isBiometricPrompt()
+ ", listener: " + listener
+ ", requireConfirmation: " + mRequireConfirmation
+ ", user: " + getTargetUserId()
+ ", clientMonitor: " + toString());
final PerformanceTracker pm = PerformanceTracker.getInstanceForSensorId(getSensorId());
if (isCryptoOperation()) {
pm.incrementCryptoAuthForUser(getTargetUserId(), authenticated);
} else {
pm.incrementAuthForUser(getTargetUserId(), authenticated);
}
if (mAllowBackgroundAuthentication) {
Slog.w(TAG, "Allowing background authentication,"
+ " this is allowed only for platform or test invocations");
}
// Ensure authentication only succeeds if the client activity is on top.
boolean isBackgroundAuth = false;
if (!mAllowBackgroundAuthentication && authenticated
&& !Utils.isKeyguard(getContext(), getOwnerString())
&& !Utils.isSystem(getContext(), getOwnerString())) {
final List<ActivityManager.RunningTaskInfo> tasks =
mActivityTaskManager.getTasks(1);
if (tasks == null || tasks.isEmpty()) {
Slog.e(TAG, "No running tasks reported");
isBackgroundAuth = true;
} else {
final ComponentName topActivity = tasks.get(0).topActivity;
if (topActivity == null) {
Slog.e(TAG, "Unable to get top activity");
isBackgroundAuth = true;
} else {
final String topPackage = topActivity.getPackageName();
if (!topPackage.contentEquals(getOwnerString())) {
Slog.e(TAG, "Background authentication detected, top: " + topPackage
+ ", client: " + getOwnerString());
isBackgroundAuth = true;
}
}
}
}
// Fail authentication if we can't confirm the client activity is on top.
if (isBackgroundAuth) {
Slog.e(TAG, "Failing possible background authentication");
authenticated = false;
// SafetyNet logging for exploitation attempts of b/159249069.
final ApplicationInfo appInfo = getContext().getApplicationInfo();
EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
"Attempted background authentication");
}
if (authenticated) {
// SafetyNet logging for b/159249069 if constraint is violated.
if (isBackgroundAuth) {
final ApplicationInfo appInfo = getContext().getApplicationInfo();
EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
"Successful background authentication!");
}
markAlreadyDone();
if (mTaskStackListener != null) {
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
}
final byte[] byteToken = new byte[hardwareAuthToken.size()];
for (int i = 0; i < hardwareAuthToken.size(); i++) {
byteToken[i] = hardwareAuthToken.get(i);
}
if (mIsStrongBiometric) {
mBiometricManager.resetLockoutTimeBound(getToken(),
getContext().getOpPackageName(),
getSensorId(), getTargetUserId(), byteToken);
}
final CoexCoordinator coordinator = CoexCoordinator.getInstance();
coordinator.onAuthenticationSucceeded(SystemClock.uptimeMillis(), this,
new CoexCoordinator.Callback() {
@Override
public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
if (addAuthTokenIfStrong && mIsStrongBiometric) {
final int result = KeyStore.getInstance().addAuthToken(byteToken);
Slog.d(TAG, "addAuthToken: " + result);
} else {
Slog.d(TAG, "Skipping addAuthToken");
}
if (listener != null) {
try {
// Explicitly have if/else here to make it super obvious in case the
// code is touched in the future.
if (!mIsRestricted) {
listener.onAuthenticationSucceeded(getSensorId(),
identifier,
byteToken,
getTargetUserId(),
mIsStrongBiometric);
} else {
listener.onAuthenticationSucceeded(getSensorId(),
null /* identifier */,
byteToken,
getTargetUserId(),
mIsStrongBiometric);
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to notify listener", e);
}
} else {
Slog.w(TAG, "Client not listening");
}
}
@Override
public void sendHapticFeedback() {
if (listener != null && mShouldVibrate) {
vibrateSuccess();
}
}
@Override
public void handleLifecycleAfterAuth() {
AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
}
@Override
public void sendAuthenticationCanceled() {
sendCancelOnly(listener);
}
});
} else {
// Allow system-defined limit of number of attempts before giving up
final @LockoutTracker.LockoutMode int lockoutMode =
handleFailedAttempt(getTargetUserId());
if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
markAlreadyDone();
}
final CoexCoordinator coordinator = CoexCoordinator.getInstance();
coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
new CoexCoordinator.Callback() {
@Override
public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
if (listener != null) {
try {
listener.onAuthenticationFailed(getSensorId());
} catch (RemoteException e) {
Slog.e(TAG, "Unable to notify listener", e);
}
}
}
@Override
public void sendHapticFeedback() {
if (listener != null && mShouldVibrate) {
vibrateError();
}
}
@Override
public void handleLifecycleAfterAuth() {
AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
}
@Override
public void sendAuthenticationCanceled() {
sendCancelOnly(listener);
}
});
}
}
然后回传到第109行,listener.onAuthenticationSucceeded
看看listener对象实例是什么
FaceService#authenticate方法中,即new ClientMonitorCallbackConverter(receiver)对象实例
所以,listener.onAuthenticationSucceeded调用的是ClientMonitorCallbackConverter#onAuthenticationSucceeded,代码如下
public class ClientMonitorCallbackConverter {
private IBiometricSensorReceiver mSensorReceiver; // BiometricService
private IFaceServiceReceiver mFaceServiceReceiver; // FaceManager
private IFingerprintServiceReceiver mFingerprintServiceReceiver; // FingerprintManager
public ClientMonitorCallbackConverter(IBiometricSensorReceiver sensorReceiver) {
mSensorReceiver = sensorReceiver;
}
public ClientMonitorCallbackConverter(IFaceServiceReceiver faceServiceReceiver) {
mFaceServiceReceiver = faceServiceReceiver;
}
public ClientMonitorCallbackConverter(IFingerprintServiceReceiver fingerprintServiceReceiver) {
mFingerprintServiceReceiver = fingerprintServiceReceiver;
}
// The following apply to all clients
void onAcquired(int sensorId, int acquiredInfo, int vendorCode) throws RemoteException {
if (mSensorReceiver != null) {
mSensorReceiver.onAcquired(sensorId, acquiredInfo, vendorCode);
} else if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onAcquired(acquiredInfo, vendorCode);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onAcquired(acquiredInfo, vendorCode);
}
}
void onAuthenticationSucceeded(int sensorId, BiometricAuthenticator.Identifier identifier,
byte[] token, int userId, boolean isStrongBiometric) throws RemoteException {
if (mSensorReceiver != null) {
mSensorReceiver.onAuthenticationSucceeded(sensorId, token);
} else if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onAuthenticationSucceeded((Face) identifier, userId,
isStrongBiometric);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onAuthenticationSucceeded((Fingerprint) identifier, userId,
isStrongBiometric);
}
}
void onAuthenticationFailed(int sensorId) throws RemoteException {
if (mSensorReceiver != null) {
mSensorReceiver.onAuthenticationFailed(sensorId);
} else if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onAuthenticationFailed();
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onAuthenticationFailed();
}
}
public void onError(int sensorId, int cookie, int error, int vendorCode)
throws RemoteException {
if (mSensorReceiver != null) {
mSensorReceiver.onError(sensorId, cookie, error, vendorCode);
} else if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onError(error, vendorCode);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onError(error, vendorCode);
}
}
// The following only apply to IFingerprintServiceReceiver and IFaceServiceReceiver
public void onDetected(int sensorId, int userId, boolean isStrongBiometric)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onFaceDetected(sensorId, userId, isStrongBiometric);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onFingerprintDetected(sensorId, userId, isStrongBiometric);
}
}
void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onEnrollResult((Face) identifier, remaining);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onEnrollResult((Fingerprint) identifier, remaining);
}
}
void onRemoved(BiometricAuthenticator.Identifier identifier, int remaining)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onRemoved((Face) identifier, remaining);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onRemoved((Fingerprint) identifier, remaining);
}
}
/** Called when a challenged has been generated. */
public void onChallengeGenerated(int sensorId, int userId, long challenge)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onChallengeGenerated(sensorId, userId, challenge);
} else if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onChallengeGenerated(sensorId, userId, challenge);
}
}
public void onFeatureSet(boolean success, int feature) throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onFeatureSet(success, feature);
}
}
public void onFeatureGet(boolean success, int[] features, boolean[] featureState)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onFeatureGet(success, features, featureState);
}
}
// Fingerprint-specific callbacks for FingerprintManager only
public void onUdfpsPointerDown(int sensorId) throws RemoteException {
if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onUdfpsPointerDown(sensorId);
}
}
public void onUdfpsPointerUp(int sensorId) throws RemoteException {
if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onUdfpsPointerUp(sensorId);
}
}
// Face-specific callbacks for FaceManager only
/**
* Called each time a new frame is received during face authentication.
*
* @param frame Information about the current frame.
*
* @throws RemoteException If the binder call to {@link IFaceServiceReceiver} fails.
*/
public void onAuthenticationFrame(@NonNull FaceAuthenticationFrame frame)
throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onAuthenticationFrame(frame);
}
}
/**
* Called each time a new frame is received during face enrollment.
*
* @param frame Information about the current frame.
*
* @throws RemoteException If the binder call to {@link IFaceServiceReceiver} fails.
*/
public void onEnrollmentFrame(@NonNull FaceEnrollFrame frame) throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onEnrollmentFrame(frame);
}
}
}
第35行的mFaceServiceReceiver 就是reveiever对象实例。其对应的源码在FaceManager.java下。
程序回调到第14行的onAuthenticationSucceeded
private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
@Override // binder call
public void onEnrollResult(Face face, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, face).sendToTarget();
}
@Override // binder call
public void onAcquired(int acquireInfo, int vendorCode) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode).sendToTarget();
}
@Override // binder call
public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {
mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId,
isStrongBiometric ? 1 : 0, face).sendToTarget();
}
@Override // binder call
public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
mHandler.obtainMessage(MSG_FACE_DETECTED, sensorId, userId, isStrongBiometric)
.sendToTarget();
}
@Override // binder call
public void onAuthenticationFailed() {
mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
}
@Override // binder call
public void onError(int error, int vendorCode) {
mHandler.obtainMessage(MSG_ERROR, error, vendorCode).sendToTarget();
}
@Override // binder call
public void onRemoved(Face face, int remaining) {
mHandler.obtainMessage(MSG_REMOVED, remaining, 0, face).sendToTarget();
}
@Override
public void onFeatureSet(boolean success, int feature) {
mHandler.obtainMessage(MSG_SET_FEATURE_COMPLETED, feature, 0, success).sendToTarget();
}
@Override
public void onFeatureGet(boolean success, int[] features, boolean[] featureState) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = success;
args.arg2 = features;
args.arg3 = featureState;
mHandler.obtainMessage(MSG_GET_FEATURE_COMPLETED, args).sendToTarget();
}
@Override
public void onChallengeGenerated(int sensorId, int userId, long challenge) {
mHandler.obtainMessage(MSG_CHALLENGE_GENERATED, sensorId, userId, challenge)
.sendToTarget();
}
@Override
public void onAuthenticationFrame(FaceAuthenticationFrame frame) {
mHandler.obtainMessage(MSG_AUTHENTICATION_FRAME, frame).sendToTarget();
}
@Override
public void onEnrollmentFrame(FaceEnrollFrame frame) {
mHandler.obtainMessage(MSG_ENROLLMENT_FRAME, frame).sendToTarget();
}
}
第15行,通过mHandler跳转到
case MSG_AUTHENTICATION_SUCCEEDED:
sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */,
msg.arg2 == 1 /* isStrongBiometric */);
break;
private void sendAuthenticatedSucceeded(Face face, int userId, boolean isStrongBiometric) {
if (mAuthenticationCallback != null) {
final AuthenticationResult result =
new AuthenticationResult(mCryptoObject, face, userId, isStrongBiometric);
mAuthenticationCallback.onAuthenticationSucceeded(result);
}
}
这里的mAuthenticationCallback就是文章开头部分有介绍,搜索
mAuthenticationCallback = callback
我们继续追踪callback变量,他实际上就是KeyguardUpdateMonitor#startListeningForFace方法中传入了这个对象。其对应的变量是mFaceAuthenticationCallback。
然后找到其对应的方法onAuthenticationSucceeded,即设别成功告知了上层用户。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)