Android R系统Fingerprint指纹流程归纳

2023-05-16

孩子长大,倘无才能,可寻点小事情过活,万不可做空头文学家或美术家。

                                                                                   ------ 鲁迅


1. Android R中framework中需要新的配置项才会在SetupWizard中启动Settings的BiometricEnrollActivity界面,否则不会启动指纹录制流程。

    <!-- List of biometric sensors on the device, in decreasing strength. Consumed by AuthService
         when registering authenticators with BiometricService. Format must be ID:Modality:Strength,
         where: IDs are unique per device, Modality as defined in BiometricAuthenticator.java,
         and Strength as defined in Authenticators.java -->
    <string-array name="config_biometric_sensors" translatable="false" >
        <!-- <item>0:2:15</item>  ID0:Fingerprint:Strong --> // 这里要定义,否则在服务初始化registerAuthenticator阶段,将没有监测到物理sensor:BIOMETRIC_ERROR_HW_NOT_PRESENT
    </string-array>

2. SetupWizard/Settings中录制指纹成功后,SystemUI模块中灭屏逻辑(KeyguardUpdateMonitor::handleStartedGoingToSleep)会去触发启动指纹验证解锁流程。

    判断是否可以启动指纹监听:shouldListenForFingerprint--> startListeningForFingerprint --> 调用authenticate方法进入系统层面,这里传入了回调函数mFingerprintAuthenticationCallback用于接受后续的验证成功失败以及错误等回调。

系统端的authenticate方法会去调用FingerprintServiceWrapper类,这个是FingerpringManager和FingerprintService的server端,通过其binder call也可见是manager的server端。

    /**
     * Receives the incoming binder calls from FingerprintManager.
     */
    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {

    @Override // Binder call
        public long preEnroll(IBinder token) {}

    @Override // Binder call
        public int postEnroll(IBinder token) {}

    @Override // Binder call
        public void enroll(final IBinder token, final byte[] cryptoToken, final int     
              userId, final IFingerprintServiceReceiver receiver, final int flags,final 
              String opPackageName) {}

    @Override // Binder call
        public void authenticate(final IBinder token, final long opId, final int 
              groupId, final IFingerprintServiceReceiver receiver, final int flags,
              final String opPackageName) {}

    @Override // Binder call
        public void remove(final IBinder token, final int fingerId, final int groupId,
                final int userId, final IFingerprintServiceReceiver receiver) {}

    @Override // Binder call
        public void rename(final int fingerId, final int groupId, final String name) {}
    …………………………

}

authenticate --> BiometricServiceBase::authenticateInternal  --> startAuthentication  -->startClient  --> mCurrentClient.start() ==> AuthenticationClient类中的start方法。

在调用过程中authenticateInternal之前,我们创建了client实例,其扩展了AuthenticationClientImpl以及父类AuthenticationClient以及ClientMonitor:

final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
                    mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
                    mCurrentUserId, groupId, opId, restricted, opPackageName,
                    0 /* cookie */, false /* requireConfirmation */);

其中,SystemUI传入的callback回调,保存在了Manager端的mAuthenticationCallback中,以参数的形式将另外的mServiceReceiver传入了ServiceListenerImpl类中,这个后面会用于回调到SystemUI中。

与daemon通信,DaemonWrapper是FingerprintService的内部辅助类,封装具体调用到Fingerprint Daemon服务的逻辑。

mCurrentClient.start(){
    int result = getDaemonWrapper().authenticate(mOpId, getGroupId());
}

    /**
     * Wraps the HAL-specific code and is passed to the ClientMonitor implementations 
       so that they
     * can be shared between the multiple biometric services.
     */
    private final DaemonWrapper mDaemonWrapper = new DaemonWrapper() {
        @Override
        public int authenticate(long operationId, int groupId) throws RemoteException 
        {
            IBiometricsFingerprint daemon = getFingerprintDaemon();
            return daemon.authenticate(operationId, groupId);
        }

        @Override
        public int cancel() throws RemoteException {
            IBiometricsFingerprint daemon = getFingerprintDaemon();
            return daemon.cancel();
        }

        @Override
        public int remove(int groupId, int biometricId) throws RemoteException {
            IBiometricsFingerprint daemon = getFingerprintDaemon();
            return daemon.remove(groupId, biometricId);
        }

        @Override
        public int enumerate() throws RemoteException {
            IBiometricsFingerprint daemon = getFingerprintDaemon();
            return daemon.enumerate();
        }

        @Override
        public int enroll(byte[] cryptoToken, int groupId, int timeout,
                ArrayList<Integer> disabledFeatures) throws RemoteException {
            IBiometricsFingerprint daemon = getFingerprintDaemon();
            return daemon.enroll(cryptoToken, groupId, timeout);
        }
    };


    /** Gets the fingerprint daemon */
    private synchronized IBiometricsFingerprint getFingerprintDaemon() {
        if (mDaemon == null) {
            Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
            try {
                // 获取daemon服务
                mDaemon = IBiometricsFingerprint.getService();
            } catch (java.util.NoSuchElementException e) {
                // Service doesn't exist or cannot be opened. Logged below.
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to get biometric interface", e);
            }
            if (mDaemon == null) {
                Slog.w(TAG, "fingerprint HIDL not available");
                return null;
            }

            mDaemon.asBinder().linkToDeath(this, 0);

            try {
                //设置hal daemon到Fingerprint service的回调接口,获取hal设备id。
                mHalDeviceId = mDaemon.setNotify(mDaemonCallback);  
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to open fingerprint HAL", e);
                mDaemon = null; // try again later!
            }

            if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
            if (mHalDeviceId != 0) {
                loadAuthenticatorIds();
                updateActiveGroup(ActivityManager.getCurrentUser(), null);
                doTemplateCleanupForUser(ActivityManager.getCurrentUser());
            } else {
                Slog.w(TAG, "Failed to open Fingerprint HAL!");
                MetricsLogger.count(getContext(), "fingerprintd_openhal_error", 1);
                mDaemon = null;
            }
        }
        return mDaemon;
    }

HAL后面的逻辑这里不分析(后续完善)。当SystemUI通过authenticate启动验证流程后,指纹端就随时监听器件,当有手指按压触发中断,设备端会通过设置到hal的mDaemonCallback回调,调用onAcquired以及onAuthenticated,onAuthenticated方法中携带有指纹验证相关数据。

mDaemonCallback::onAuthenticated --> BiometricServiceBase::handleAuthenticated  --> client.onAuthenticated

client是我们之前调用authenticateInternal之前构建的AuthenticationClientImpl,其实现的方法在父类AuthenticationClient中,通过验证identifier的id确认是否通过指纹验证。

final boolean authenticated = identifier.getBiometricId() != 0;

// 这里的listener同样是我们在authenticate时构建的new ServiceListenerImpl(receiver,其receiver就是SystemUI的回调方法。
final BiometricServiceBase.ServiceListener listener = getListener();
if (authenticated) {
    listener.onAuthenticationSucceeded();
} else {
    listener.onAuthenticationFailedInternal();
}
   /**
     * Receives callbacks from the ClientMonitor implementations. The results are forwarded to
     * the FingerprintManager.
     */
    private class ServiceListenerImpl implements ServiceListener {
        private IFingerprintServiceReceiver mFingerprintServiceReceiver;

        public ServiceListenerImpl(IFingerprintServiceReceiver receiver) {
            mFingerprintServiceReceiver = receiver;
        }

        @Override
        public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining)
                throws RemoteException {
            if (mFingerprintServiceReceiver != null) {
                final Fingerprint fp = (Fingerprint) identifier;
                mFingerprintServiceReceiver.onEnrollResult(fp.getDeviceId(), fp.getBiometricId(),
                        fp.getGroupId(), remaining);
            }
        }

        @Override
        public void onAcquired(long deviceId, int acquiredInfo, int vendorCode)
                throws RemoteException {
            if (mFingerprintServiceReceiver != null) {
                mFingerprintServiceReceiver.onAcquired(deviceId, acquiredInfo, vendorCode);
            }
        }

        @Override
        public void onAuthenticationSucceeded(long deviceId,
                BiometricAuthenticator.Identifier biometric, int userId)
                throws RemoteException {
            if (mFingerprintServiceReceiver != null) {
                if (biometric == null || biometric instanceof Fingerprint) {
                    mFingerprintServiceReceiver.onAuthenticationSucceeded(deviceId,
                            (Fingerprint) biometric, userId, isStrongBiometric());
                } else {
                    Slog.e(TAG, "onAuthenticationSucceeded received non-fingerprint biometric");
                }
            }
        }

        @Override
        public void onAuthenticationFailed(long deviceId) throws RemoteException {
            if (mFingerprintServiceReceiver != null) {
                mFingerprintServiceReceiver.onAuthenticationFailed(deviceId);
            }
        }

        @Override
        public void onError(long deviceId, int error, int vendorCode, int cookie)
                throws RemoteException {
            if (mFingerprintServiceReceiver != null) {
                mFingerprintServiceReceiver.onError(deviceId, error, vendorCode);
            }
        }
    }

这里的mFingerprintServiceReceiver是authenticate时,传入的manager内部类,负责将结果进一步封装,通过handler机制,传递回SystemUI中。

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,
                boolean isStrongBiometric) {
            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 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();
        }
    };

sendAuthenticatedSucceeded方法中的mAuthenticationCallback,即:

// SystemUI中代码:
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mFingerprintAuthenticationCallback,
                    null, userId);

// 系统处理callback,保存到mAuthenticationCallback
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal 
              cancel,int flags, @NonNull AuthenticationCallback callback, Handler 
              handler, int userId) {
        if (callback == null) {
            throw new IllegalArgumentException("Must supply an authentication callback");
        }

        if (mService != null) try {
            useHandler(handler);
            mAuthenticationCallback = callback;
            mCryptoObject = crypto;
            long sessionId = crypto != null ? crypto.getOpId() : 0;
            Slog.i("fingerprint_linhui","authenticate, pkg="+mContext.getOpPackageName(), new Throwable());
            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
                    mContext.getOpPackageName());


// sendAuthenticatedSucceeded中调用回SystemUI:
    private void sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) {
        if (mAuthenticationCallback != null) {
            final AuthenticationResult result =
                    new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric);
            mAuthenticationCallback.onAuthenticationSucceeded(result);
        }
    }
}

我们SystemUI中通过如下方法传入的回调了mFingerprintAuthenticationCallback,所以接下来就进入到了SystemUI中的逻辑:

private FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
            = new AuthenticationCallback() {

        @Override
        public void onAuthenticationFailed() {
            handleFingerprintAuthFailed();
        }

        @Override
        public void onAuthenticationSucceeded(AuthenticationResult result) {
            handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
        }
}

接着就是走解锁的逻辑: onBiometricAuthenticated  --> startWakeAndUnlock,后续不再赘述,解锁失败也是同样的回调逻辑。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android R系统Fingerprint指纹流程归纳 的相关文章

随机推荐