美文网首页
Android 人脸解锁源码剖析

Android 人脸解锁源码剖析

作者: 程序员Android1 | 来源:发表于2021-08-25 09:36 被阅读0次

    和你一起终身学习,这里是程序员 Android

    经典好文推荐,通过阅读本文,您将收获以下知识点:

    一、人脸识别身份验证HIDL
    二、人脸模块流程分析
    三、人脸录入
    四、人脸匹配
    五、人脸解锁屏幕

    一、人脸识别身份验证HIDL

    借助人脸识别身份验证功能,用户只需要将自己的面孔对准设备即可将其解锁。Android 10 增加了对一种新的人脸识别身份验证堆栈的支持,这种堆栈可安全处理摄像头帧,从而在支持的硬件上进行人脸识别身份验证时保障安全和隐私。Android 10 还提供了一种简单的安全合规实现方法,以支持通过应用集成来完成交易(例如网上银行或其他服务)。
    Android 人脸识别身份验证堆栈是Android 10中的新实现。该实现引入了 IBiometricsFace.hal、IBiometricsFaceClientCallback.hal、和type.hal接口。

    要实现Face HIDL,你必须在某个供应商专用库中实现 IBiometricsFace.hal的所有方法
    人脸识别架构
    BiometricPrompt API包括人脸识别、指纹识别和虹膜识别在内的所有生物识别身份验证方法。Face HAL会与以下组件交互:

    FaceManager

    FaceManager是一个私有接口,用于维护FaceService的之间连接。Keyguard通过该接口访问具有自定义界面的人脸识别身份验证硬件。应用无权访问FaceManager,必须改为使用BiometricPrompt。

    FaceService

    该框架实现用于管理对人脸识别身份验证硬件的访问权限。它包含基本的注册和身份验证状态机以及各种其他辅助程序(例如枚举程序)。处于稳定性和安全性方面的考虑,不允许在此进程中运行任何供应商代码。所有供应商代码都通过Face 1.0 HIDL接口访问。

    faced

    这是一个Linux可执行文件,用于实现供FaceService使用的Face 1.0 HIDL 接口。它会将自身注册为 IBiometricsFace@1.0以便FaceService能够找到它。

    二、人脸模块流程分析

    要实现Face HIDL,你必须在某个供应商专用库中实现 IBiometricsFace.hal的所有方法

    IBiometricsFace.hal中主要包括以下主要方法:setCallback(); setActiveUser(); revokeChallenge(); enroll(); cancel(); enumerate(); remove(); authenticate(); userActivity; resetLockout(); 其余的四个都是同步方法,应将其阻塞时间缩至最短以免拖延框架。它们分别是generateChallenge(); setFeature(); getFeature; getAuthentitorId()

    人脸模块中的录入,匹配,移除是三个大部分;

    三、人脸录入

    人脸录入的入口在Settings中的FaceEnrollEnrolling.java中

    在这个类中没有看到明显的录入的方法,只有一些UI的加载和一些录入动画的逻辑。

    在此类中的on EnrollmentProgressChange(int steps, int remaining)更新录入进度的方法中用通过传递进来的remaining来获取实际的进度;当remaining = 0 时打开录入结束界面launchFinish(mToken);

    packages/apps/Settings/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java

    
        @Override
        public void onEnrollmentProgressChange(int steps, int remaining) {
            if (DEBUG) {
                Log.v(TAG, "Steps: " + steps + " Remaining: " + remaining);
            }
            /*重点关注*/
            mPreviewFragment.onEnrollmentProgressChange(steps, remaining);
    
            // TODO: Update the actual animation
            showError("Steps: " + steps + " Remaining: " + remaining);
    
            // TODO: Have this match any animations that UX comes up with
            if (remaining == 0) {
                launchFinish(mToken);
            }
        
    

    packages/apps/Settings/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java

        @Override
        public void onEnrollmentProgressChange(int steps, int remaining) {
            /*重点关注*/
            mAnimationDrawable.onEnrollmentProgressChange(steps, remaining);
        }
    
    

    packages/apps/Settings/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java

    
        @Override
        public void onEnrollmentProgressChange(int steps, int remaining) {
            /*重点关注*/
            mParticleCollection.onEnrollmentProgressChange(steps, remaining);
        }
    
    

    packages/apps/Settings/src/com/android/settings/biometrics/face/ParticleCollection.java

    /*重点关注*/
    public class ParticleCollection implements BiometricEnrollSidecar.Listener {
        ......
        @Override
        public void onEnrollmentProgressChange(int steps, int remaining) {
            if (remaining == 0) {
                updateState(STATE_COMPLETE);
            }
        }
    }
    
    

    由此可以看出此类是实现了BiometricEnrollSidecar.Listener从而调用onEnrollmentProgressChange通过传入的remaining值对录入人脸的进度条进行更新的

    packages/apps/Settings/src/com/android/settings/biometrics/BiometricEnrollSidecar.java

    
    public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
    
        public interface Listener {
            void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
            void onEnrollmentError(int errMsgId, CharSequence errString);
            /*重点关注*/
            void onEnrollmentProgressChange(int steps, int remaining);
        }
    
    
    

    onEnrollmentProgressChange

        protected void onEnrollmentProgress(int remaining) {
            if (mEnrollmentSteps == -1) {
                mEnrollmentSteps = remaining;
            }
            mEnrollmentRemaining = remaining;
            mDone = remaining == 0;
            if (mListener != null) {
                /*重点关注*/
                mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
            } else {
                mQueuedEvents.add(new QueuedEnrollmentProgress(mEnrollmentSteps, remaining));
            }
        }
    
    

    底层在录制人脸的时候会在FaceManager中调用onEnrollmentProgress方法,并将进度remainiing返回过来,BiometricEnrollSidecar内部写有Listener,在使用Listener的对象将onEnrollmentProgress的值传递进去,使更多实现Listener接口的类可以接收到

    packages/apps/Settings/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
    我们再回到这个类中去看看startEnrollment录入的方法

    
        @Override
        public void startEnrollment() {
            /*重点关注*/
            super.startEnrollment();
            mPreviewFragment = (FaceEnrollPreviewFragment) getSupportFragmentManager()
                    .findFragmentByTag(TAG_FACE_PREVIEW);
            if (mPreviewFragment == null) {
                mPreviewFragment = new FaceEnrollPreviewFragment();
                getSupportFragmentManager().beginTransaction().add(mPreviewFragment, TAG_FACE_PREVIEW)
                        .commitAllowingStateLoss();
            }
            mPreviewFragment.setListener(mListener);
        }
    
    

    此方法中没有明显录入的方法,可见录入方法存在于他的父类中

    packages/apps/Settings/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java

        public void startEnrollment() {
            mSidecar = (BiometricEnrollSidecar) getSupportFragmentManager()
                    .findFragmentByTag(TAG_SIDECAR);
            if (mSidecar == null) {
                mSidecar = getSidecar();
                getSupportFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR)
                        .commitAllowingStateLoss();
            }
            /*重点关注*/
            mSidecar.setListener(this);
        }
    
    
    

    由此可知是通过给mSidecar设置setListener监听传入变化而开始录入的

    packages/apps/Settings/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java

        @Override
        public void startEnrollment() {
            super.startEnrollment();
            if (mUserId != UserHandle.USER_NULL) {
                mFaceManager.setActiveUser(mUserId);
            }
            /*重点关注*/
            mFaceManager.enroll(mToken, mEnrollmentCancel,
                    mEnrollmentCallback, mDisabledFeatures);
        }
    
    

    frameworks/base/core/java/android/hardware/face/FaceManager.java

        public void enroll(byte[] token, CancellationSignal cancel,
                EnrollmentCallback callback, int[] disabledFeatures) {
            if (callback == null) {
                throw new IllegalArgumentException("Must supply an enrollment callback");
            }
    
            if (cancel != null) {
                if (cancel.isCanceled()) {
                    Log.w(TAG, "enrollment already canceled");
                    return;
                } else {
                    cancel.setOnCancelListener(new OnEnrollCancelListener());
                }
            }
    
            if (mService != null) {
                try {
                    mEnrollmentCallback = callback;
                    Trace.beginSection("FaceManager#enroll");
                    /*重点关注*/
                    mService.enroll(mToken, token, mServiceReceiver,
                            mContext.getOpPackageName(), disabledFeatures);
                } catch (RemoteException e) {
                    Log.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(FACE_ERROR_HW_UNAVAILABLE,
                                getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
                                    0 /* vendorCode */));
                    }
                } finally {
                    Trace.endSection();
                }
            }
        }
        
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/face/FaceService.java

            public void enroll(final IBinder token, final byte[] cryptoToken,
                    final IFaceServiceReceiver receiver, final String opPackageName,
                    final int[] disabledFeatures) {
                checkPermission(MANAGE_BIOMETRIC);
    
                final boolean restricted = isRestricted();
                final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper,
                        mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId,
                        0 /* groupId */, cryptoToken, restricted, opPackageName, disabledFeatures) {
    
                    @Override
                    public int[] getAcquireIgnorelist() {
                        return mEnrollIgnoreList;
                    }
    
                    @Override
                    public int[] getAcquireVendorIgnorelist() {
                        return mEnrollIgnoreListVendor;
                    }
    
                    @Override
                    public boolean shouldVibrate() {
                        return false;
                    }
    
                    @Override
                    protected int statsModality() {
                        return FaceService.this.statsModality();
                    }
                };
                /*重点关注*/
                enrollInternal(client, mCurrentUserId);
            }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

            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(client, true /* initiatedByClient */);

            ClientMonitor currentClient = mCurrentClient;
            if (currentClient != null) {
                if (DEBUG) Slog.v(getTag(), "request stop current client " +
                        currentClient.getOwnerString());
                // This check only matters for FingerprintService, since enumerate may call back
                // multiple times.
                if (currentClient instanceof InternalEnumerateClient
                        || currentClient instanceof InternalRemovalClient) {
                    // This condition means we're currently running internal diagnostics to
                    // remove extra templates in the hardware and/or the software
                    // TODO: design an escape hatch in case client never finishes
                    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);
    
                    // Only post the reset runnable for non-cleanup clients. Cleanup clients should
                    // never be forcibly stopped since they ensure synchronization between HAL and
                    // framework. Thus, we should instead just start the pending client once cleanup
                    // finishes instead of using the reset runnable.
                    mHandler.removeCallbacks(mResetClientState);
                    mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
                }
                mPendingClient = newClient;
            } else if (newClient != null) {
                // For BiometricPrompt clients, do not start until
                // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
                // modalities are ready before initiating authentication.
                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());
    
            
            }
        }
        
    
    

    在此将EnrollClient的对象传进去

    startCurrentClient(mCurrentClient.getCookie());

        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() + ")"
                    + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
            if (cookie != mCurrentClient.getCookie()) {
                Slog.e(getTag(), "Mismatched cookie");
                return;
            }
            notifyClientActiveCallbacks(true);
            /*重点关注*/
            mCurrentClient.start();
        }
       
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/EnrollClient.java

        @Override
        public int start() {
            mEnrollmentStartTimeMs = System.currentTimeMillis();
            final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
            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(), timeout,
                        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
        }
    
    

    start 方法会调用faced,调用底层的人脸库,底层库返回结果后会调用onEnrollResult来反馈结果receiver,再往上层反馈。这就是人脸的录制流程。在onEnrollResult中当remaining等于0的时候完成录制,调用addBiometricForUser。

    FaceManager.java中注册了IFaceServiceReceiver,实现onEnrollResult方法发送 MSG_ENROLL_RESULT
    frameworks/base/core/java/android/hardware/face/FaceManager.java

        private IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
    
            @Override // binder call
            public void onEnrollResult(long deviceId, int faceId, int remaining) {
                /*重点关注*/
                mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
                        new Face(null, faceId, deviceId)).sendToTarget();
            }
            ...
    
    

    MSG_ENROLL_RESULT

            public void handleMessage(android.os.Message msg) {
                Trace.beginSection("FaceManager#handleMessage: " + Integer.toString(msg.what));
                switch (msg.what) {
                    case MSG_ENROLL_RESULT:
                        /*重点关注*/
                        sendEnrollResult((Face) msg.obj, msg.arg1 /* remaining */);
                        break;
                        ...
    
    

    sendEnrollResult

    private void sendEnrollResult(Face face, int remaining) {
            if (mEnrollmentCallback != null) {
                mEnrollmentCallback.onEnrollmentProgress(remaining);
            }
        }
    
    

    四、人脸匹配

    人脸解锁的入口在Keyguard中

    系统灭屏之后会调用PhoneWindowManager的startedGoingToSleep方法,继而调用KeyguardDelegate.onStartedGoingToSleep方法。

    继而又会调用KeyguardServiceWrapper.java ==》onStartedGoingToSleep()方法;再调用KeyguardService.java ==》onStartedGoingToSleep()方法;并最终在KeyguardViewMediator.java ==》dispatchStartedGoingToSleep() 达到对GoingToSleep事件的监听

    frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java

    public void dispatchStartedGoingToSleep(int why) {
            /*重点关注*/
            mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0));
        }
    
    

    MSG_STARTED_GOING_TO_SLEEP

    case MSG_STARTED_GOING_TO_SLEEP:
                        /*重点关注*/
                        handleStartedGoingToSleep(msg.arg1);
                        break;
    

    handleStartedGoingToSleep(msg.arg1);

        protected void handleStartedGoingToSleep(int arg1) {
            clearBiometricRecognized();
            final int count = mCallbacks.size();
            for (int i = 0; i < count; i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    cb.onStartedGoingToSleep(arg1);
                }
            }
            mGoingToSleep = true;
            /*重点关注*/
            updateBiometricListeningState();//更新生物识别状态
        }
    
    

    updateBiometricListeningState()

     //在这个方法中我们可以看到同时更新了指纹和人脸的状态
        private void updateBiometricListeningState() {
            updateFingerprintListeningState();
            /*重点关注*/
            updateFaceListeningState();
        }
    
    

    updateFaceListeningState()

    
        private void updateFaceListeningState() {
            // If this message exists, we should not authenticate again until this message is
            // consumed by the handler
            if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
                return;
            }
            mHandler.removeCallbacks(mRetryFaceAuthentication);
            boolean shouldListenForFace = shouldListenForFace();
            if (mFaceRunningState == BIOMETRIC_STATE_RUNNING && !shouldListenForFace) {
                stopListeningForFace();
            } else if (mFaceRunningState != BIOMETRIC_STATE_RUNNING
                    && shouldListenForFace) {
                /*重点关注*/
                startListeningForFace();
            }
        }
    
    

    startListeningForFace()

    
        private void startListeningForFace() {
            if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
                setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
                return;
            }
            if (DEBUG) Log.v(TAG, "startListeningForFace()");
            int userId = getCurrentUser();
            if (isUnlockWithFacePossible(userId)) {
                if (mFaceCancelSignal != null) {
                    mFaceCancelSignal.cancel();
                }
                mFaceCancelSignal = new CancellationSignal();
                /*重点关注*/
                mFaceManager.authenticate(null, mFaceCancelSignal, 0,
                        mFaceAuthenticationCallback, null, userId);
                setFaceRunningState(BIOMETRIC_STATE_RUNNING);
            }
        }
    
    

    frameworks/base/core/java/android/hardware/face/FaceManager.java

    
        public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
                int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler,
                int userId) {
            if (callback == null) {
                throw new IllegalArgumentException("Must supply an authentication callback");
            }
    
            if (cancel != null) {
                if (cancel.isCanceled()) {
                    Log.w(TAG, "authentication already canceled");
                    return;
                } else {
                    cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
                }
            }
    
            if (mService != null) {
                try {
                    useHandler(handler);
                    mAuthenticationCallback = callback;
                    mCryptoObject = crypto;
                    long sessionId = crypto != null ? crypto.getOpId() : 0;
                    Trace.beginSection("FaceManager#authenticate");
                    /*重点关注*/
                    mService.authenticate(mToken, sessionId, userId, mServiceReceiver,
                            flags, mContext.getOpPackageName());
                } catch (RemoteException e) {
                    Log.w(TAG, "Remote exception while authenticating: ", e);
                    if (callback != null) {
                        // 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();
                }
            }
        }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/face/FaceService.java

    
            @Override // Binder call
            public void authenticate(final IBinder token, final long opId, int userId,
                    final IFaceServiceReceiver receiver, final int flags,
                    final String opPackageName) {
                checkPermission(USE_BIOMETRIC_INTERNAL);
                updateActiveGroup(userId, opPackageName);
                final boolean restricted = isRestricted();
                final AuthenticationClientImpl client = new FaceAuthClient(getContext(),
                        mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
                        mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
                        0 /* cookie */, false /* requireConfirmation */);
                /*重点关注*/
                authenticateInternal(client, opId, opPackageName);
            }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

    
        protected void authenticateInternal(AuthenticationClientImpl client, long opId,
                String opPackageName) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int callingUserId = UserHandle.getCallingUserId();
            authenticateInternal(client, opId, opPackageName, callingUid, callingPid, callingUserId);
        }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

    
        protected void authenticateInternal(AuthenticationClientImpl client, long opId,
                String opPackageName, int callingUid, int callingPid, int callingUserId) {
            if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
                    callingUserId)) {
                if (DEBUG) Slog.v(getTag(), "authenticate(): reject " + opPackageName);
                return;
            }
    
            mHandler.post(() -> {
                mMetricsLogger.histogram(getConstants().tagAuthToken(), opId != 0L ? 1 : 0);
    
                // Get performance stats object for this user.
                HashMap<Integer, PerformanceStats> pmap
                        = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
                PerformanceStats stats = pmap.get(mCurrentUserId);
                if (stats == null) {
                    stats = new PerformanceStats();
                    pmap.put(mCurrentUserId, stats);
                }
                mPerformanceStats = stats;
                mIsCrypto = (opId != 0);
                /*重点关注*/
                startAuthentication(client, opPackageName);
            });
        }
    
    

    startAuthentication(client, opPackageName);

        private void startAuthentication(AuthenticationClientImpl client, String opPackageName) {
            if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")");
    
            int lockoutMode = getLockoutMode();
            if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
                Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
                int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
                        BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :
                        BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
                if (!client.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */)) {
                    Slog.w(getTag(), "Cannot send permanent lockout message to client");
                }
                return;
            }
            /*重点关注*/
            startClient(client, true /* initiatedByClient */);
            //这里将AuthenticationClient传递进去
        }    
    
    

    startClient(client, true /* initiatedByClient */);

     private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
            ClientMonitor currentClient = mCurrentClient;
            if (currentClient != null) {
                if (DEBUG) Slog.v(getTag(), "request stop current client " +
                        currentClient.getOwnerString());
                // This check only matters for FingerprintService, since enumerate may call back
                // multiple times.
                if (currentClient instanceof InternalEnumerateClient
                        || currentClient instanceof InternalRemovalClient) {
                    // This condition means we're currently running internal diagnostics to
                    // remove extra templates in the hardware and/or the software
                    // TODO: design an escape hatch in case client never finishes
                    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);
    
                    // Only post the reset runnable for non-cleanup clients. Cleanup clients should
                    // never be forcibly stopped since they ensure synchronization between HAL and
                    // framework. Thus, we should instead just start the pending client once cleanup
                    // finishes instead of using the reset runnable.
                    mHandler.removeCallbacks(mResetClientState);
                    mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
                }
                mPendingClient = newClient;
            } else if (newClient != null) {
                // For BiometricPrompt clients, do not start until
                // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
                // modalities are ready before initiating authentication.
                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());
                //这里继续将AuthenticationClient传递进去
            }
        }
    
    

    startCurrentClient(mCurrentClient.getCookie());

        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() + ")"
                    + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
            if (cookie != mCurrentClient.getCookie()) {
                Slog.e(getTag(), "Mismatched cookie");
                return;
            }
            notifyClientActiveCallbacks(true);
            /*重点关注*/
            mCurrentClient.start();
            //这里调用的是AuthenticationClient的start方法
        }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/AuthenticationClient.java

        public int start() {
            mStarted = true;
            onStart();
            try {
                /*重点关注*/
                final int result = getDaemonWrapper().authenticate(mOpId, getGroupId());
                if (result != 0) {
                    Slog.w(getLogTag(), "startAuthentication failed, result=" + result);
                    mMetricsLogger.histogram(mConstants.tagAuthStartError(), result);
                    onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                            0 /* vendorCode */);
                    return result;
                }
                if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() + " is authenticating...");
            } catch (RemoteException e) {
                Slog.e(getLogTag(), "startAuthentication failed", e);
                return ERROR_ESRCH;
            }
            return 0; // success
        }
    
    

    start方法会调用faced,调用底层的人脸库,底层库返回结果后会调用onAuthenticated来反馈结果给receiver,在往上层反馈

    五、人脸解锁屏幕

    frameworks/base/services/core/java/com/android/server/biometrics/AuthenticationClient.java

        public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
                boolean authenticated, ArrayList<Byte> token) {
            super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation,
                    getTargetUserId(), isBiometricPrompt());
    
            final BiometricServiceBase.ServiceListener listener = getListener();
    
            mMetricsLogger.action(mConstants.actionBiometricAuth(), authenticated);
            boolean result = false;
    
            try {
                if (DEBUG) Slog.v(getLogTag(), "onAuthenticated(" + authenticated + ")"
                        + ", ID:" + identifier.getBiometricId()
                        + ", Owner: " + getOwnerString()
                        + ", isBP: " + isBiometricPrompt()
                        + ", listener: " + listener
                        + ", requireConfirmation: " + mRequireConfirmation
                        + ", user: " + getTargetUserId());
    
                if (authenticated) {
                    mAlreadyDone = true;
    
                    if (listener != null) {
                        vibrateSuccess();
                    }
                    result = true;
                    if (shouldFrameworkHandleLockout()) {
                        resetFailedAttempts();
                    }
                    onStop();
    
                    final byte[] byteToken = new byte[token.size()];
                    for (int i = 0; i < token.size(); i++) {
                        byteToken[i] = token.get(i);
                    }
                    if (isBiometricPrompt() && listener != null) {
                        // BiometricService will add the token to keystore
                        listener.onAuthenticationSucceededInternal(mRequireConfirmation, byteToken);
                    } else if (!isBiometricPrompt() && listener != null) {
                        KeyStore.getInstance().addAuthToken(byteToken);
                        try {
                            // Explicitly have if/else here to make it super obvious in case the code is
                            // touched in the future.
                            if (!getIsRestricted()) {
                                /*重点关注*/
                                listener.onAuthenticationSucceeded(
                                        getHalDeviceId(), identifier, getTargetUserId());
                            } else {
                                listener.onAuthenticationSucceeded(
                                        getHalDeviceId(), null, getTargetUserId());
                            }
                        } catch (RemoteException e) {
                            Slog.e(getLogTag(), "Remote exception", e);
                        }
                    } else {
                        // Client not listening
                        Slog.w(getLogTag(), "Client not listening");
                        result = true;
                    }
                } else {
                    if (listener != null) {
                        vibrateError();
                    }
    
                    // Allow system-defined limit of number of attempts before giving up
                    final int lockoutMode = handleFailedAttempt();
                    if (lockoutMode != LOCKOUT_NONE && shouldFrameworkHandleLockout()) {
                        Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode("
                                + lockoutMode + ")");
                        stop(false);
                        final int errorCode = lockoutMode == LOCKOUT_TIMED
                                ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
                                : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
                        onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
                    } else {
                        // Don't send onAuthenticationFailed if we're in lockout, it causes a
                        // janky UI on Keyguard/BiometricPrompt since "authentication failed"
                        // will show briefly and be replaced by "device locked out" message.
                        if (listener != null) {
                            if (isBiometricPrompt()) {
                                listener.onAuthenticationFailedInternal(getCookie(),
                                        getRequireConfirmation());
                            } else {
                                listener.onAuthenticationFailed(getHalDeviceId());
                            }
                        }
                    }
                    result = lockoutMode != LOCKOUT_NONE; // in a lockout mode
                }
            } catch (RemoteException e) {
                Slog.e(getLogTag(), "Remote exception", e);
                result = true;
            }
            return result;
        }
    
    

    frameworks/base/services/core/java/com/android/server/biometrics/BiometricServiceBase.java

        protected interface ServiceListener {
            default void onEnrollResult(BiometricAuthenticator.Identifier identifier,
                    int remaining) throws RemoteException {};
    
            void onAcquired(long deviceId, int acquiredInfo, int vendorCode) throws RemoteException;
    
            /*重点关注*/
            default void onAuthenticationSucceeded(long deviceId,
                    BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {
                throw new UnsupportedOperationException("Stub!");
            }
    
            default void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
                    throws RemoteException {
                throw new UnsupportedOperationException("Stub!");
            }
    
            default void onAuthenticationFailed(long deviceId) throws RemoteException {
                throw new UnsupportedOperationException("Stub!");
            }
    
            default void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
                    throws RemoteException {
                throw new UnsupportedOperationException("Stub!");
            }
    
            void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException;
    
            default void onRemoved(BiometricAuthenticator.Identifier identifier,
                    int remaining) throws RemoteException {};
    
            default void onEnumerated(BiometricAuthenticator.Identifier identifier,
                    int remaining) throws RemoteException {};
        }
    
    

    onAuthenticationSucceeded

    
        /**
         * Wraps the callback interface from Service -> BiometricPrompt
         */
        protected abstract class BiometricServiceListener implements ServiceListener {
            private IBiometricServiceReceiverInternal mWrapperReceiver;
    
            public BiometricServiceListener(IBiometricServiceReceiverInternal wrapperReceiver) {
                mWrapperReceiver = wrapperReceiver;
            }
    
            public IBiometricServiceReceiverInternal getWrapperReceiver() {
                return mWrapperReceiver;
            }
    
            @Override
            public void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
                    throws RemoteException {
                if (getWrapperReceiver() != null) {
                
                    /*重点关注*/
                    getWrapperReceiver().onAuthenticationSucceeded(requireConfirmation, token);
                }
            }
    
            @Override
            public void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
                    throws RemoteException {
                if (getWrapperReceiver() != null) {
                    getWrapperReceiver().onAuthenticationFailed(cookie, requireConfirmation);
                }
            }
        }
    
    

    frameworks/base/core/java/android/hardware/face/FaceManager.java

    
        private IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
    
        ......
    
            @Override // binder call
            public void onAuthenticationSucceeded(long deviceId, Face face, int userId) {
                /*重点关注*/
                mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, face).sendToTarget();
            }
    
    

    MSG_AUTHENTICATION_SUCCEEDED

    
    case MSG_AUTHENTICATION_SUCCEEDED:
                        /*重点关注*/
                        sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */);
                        break;
    
    

    sendAuthenticatedSucceeded

    
        private void sendAuthenticatedSucceeded(Face face, int userId) {
            if (mAuthenticationCallback != null) {
                final AuthenticationResult result =
                        new AuthenticationResult(mCryptoObject, face, userId);
                /*重点关注*/
                mAuthenticationCallback.onAuthenticationSucceeded(result);
            }
        }
    
    

    AuthenticationCallback是Fm的一个内部回调接口

    
        public abstract static class AuthenticationCallback
                extends BiometricAuthenticator.AuthenticationCallback {
    
            /**
             * Called when an unrecoverable error has been encountered and the operation is complete.
             * No further callbacks will be made on this object.
             *
             * @param errorCode An integer identifying the error message
             * @param errString A human-readable error string that can be shown in UI
             */
            public void onAuthenticationError(int errorCode, CharSequence errString) {
            }
    
            /**
             * Called when a recoverable error has been encountered during authentication. The help
             * string is provided to give the user guidance for what went wrong, such as
             * "Sensor dirty, please clean it."
             *
             * @param helpCode   An integer identifying the error message
             * @param helpString A human-readable string that can be shown in UI
             */
            public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
            }
    
            /**
             * Called when a face is recognized.
             *
             * @param result An object containing authentication-related data
             */
             /*重点关注*/
            public void onAuthenticationSucceeded(AuthenticationResult result) {
            }
    
            /**
             * Called when a face is detected but not recognized.
             */
            public void onAuthenticationFailed() {
            }
    
            /**
             * Called when a face image has been acquired, but wasn't processed yet.
             *
             * @param acquireInfo one of FACE_ACQUIRED_* constants
             * @hide
             */
            public void onAuthenticationAcquired(int acquireInfo) {
            }
        }
        
    
    

    frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java

    AuthenticationCallback接口在KeyguardUpdateMonitor.java中实现,用于监听FaceService中人脸的解锁状态

    
       @VisibleForTesting
       FaceManager.AuthenticationCallback mFaceAuthenticationCallback
               = new FaceManager.AuthenticationCallback() {
    
           @Override
           public void onAuthenticationFailed() {
               handleFaceAuthFailed();
           }
    
           @Override
           public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {
               Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
               /*重点关注*/
               handleFaceAuthenticated(result.getUserId());
               Trace.endSection();
           }
    
           @Override
           public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
               handleFaceHelp(helpMsgId, helpString.toString());
           }
    
           @Override
           public void onAuthenticationError(int errMsgId, CharSequence errString) {
               handleFaceError(errMsgId, errString.toString());
           }
    
           @Override
           public void onAuthenticationAcquired(int acquireInfo) {
               handleFaceAcquired(acquireInfo);
           }
       };
    
    

    handleFaceAuthenticated

    
        private void handleFaceAuthenticated(int authUserId) {
            Trace.beginSection("KeyGuardUpdateMonitor#handlerFaceAuthenticated");
            try {
                final int userId;
                try {
                    userId = ActivityManager.getService().getCurrentUser().id;
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to get current user id: ", e);
                    return;
                }
                if (userId != authUserId) {
                    Log.d(TAG, "Face authenticated for wrong user: " + authUserId);
                    return;
                }
                if (isFaceDisabled(userId)) {
                    Log.d(TAG, "Face authentication disabled by DPM for userId: " + userId);
                    return;
                }
                /*重点关注*/
                onFaceAuthenticated(userId);
            } finally {
                setFaceRunningState(BIOMETRIC_STATE_STOPPED);
            }
            Trace.endSection();
        }
    
    

    onFaceAuthenticated(userId)

    
        protected void onFaceAuthenticated(int userId) {
            Trace.beginSection("KeyGuardUpdateMonitor#onFaceAuthenticated");
            mUserFaceAuthenticated.put(userId, true);
            // Update/refresh trust state only if user can skip bouncer
            if (getUserCanSkipBouncer(userId)) {
                mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FACE);
            }
            // Don't send cancel if authentication succeeds
            mFaceCancelSignal = null;
            for (int i = 0; i < mCallbacks.size(); i++) {
                /*重点关注*/
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    /*重点关注*/
                    cb.onBiometricAuthenticated(userId,
                            BiometricSourceType.FACE);
                }
            }
    
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE),
                    BIOMETRIC_CONTINUE_DELAY_MS);
    
            // Only authenticate face once when assistant is visible
            mAssistantVisible = false;
    
            Trace.endSection();
        }
    
    

    这里开始调用接口将解锁成功消息层层传递直至keyguard解锁,与指纹解锁逻辑一致

    可以看到在onFaceAuthenticated(userId)方法中调用了KeyguardUpdateMonitorCallback这个抽象类的onBiometricAuthenticated()抽象方法,而BiometricUnlockController extends KeyguardUpdateMonitorCallback,并注册了回调mUpdateMonitor.registerCallback(this)

    frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java

       /**
        * Called when a biometric is recognized.
        * @param userId the user id for which the biometric sample was authenticated
        * @param biometricSourceType
        */
        /*重点关注*/
       public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { }
    
    

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java

        @Override
        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
            Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
            if (mUpdateMonitor.isGoingToSleep()) {
                mPendingAuthenticatedUserId = userId;
                mPendingAuthenticatedBioSourceType = biometricSourceType;
                Trace.endSection();
                return;
            }
            mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
                    .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
             /*重点关注*/
            startWakeAndUnlock(calculateMode(biometricSourceType));
        }
    
    

    startWakeAndUnlock(calculateMode(biometricSourceType));

        public void startWakeAndUnlock(int mode) {
            // TODO(b/62444020): remove when this bug is fixed
            Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
            boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
            mMode = mode;
            mHasScreenTurnedOnSinceAuthenticating = false;
            if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
                // If we are waking the device up while we are pulsing the clock and the
                // notifications would light up first, creating an unpleasant animation.
                // Defer changing the screen brightness by forcing doze brightness on our window
                // until the clock and the notifications are faded out.
                mStatusBarWindowController.setForceDozeBrightness(true);
            }
            // During wake and unlock, we need to draw black before waking up to avoid abrupt
            // brightness changes due to display state transitions.
            boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
            boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
            Runnable wakeUp = ()-> {
                if (!wasDeviceInteractive) {
                    if (DEBUG_BIO_WAKELOCK) {
                        Log.i(TAG, "bio wakelock: Authenticated, waking up...");
                    }
                    mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                            "android.policy:BIOMETRIC");
                }
                if (delayWakeUp) {
                   /*重点关注*/
                    mKeyguardViewMediator.onWakeAndUnlocking();
                }
                Trace.beginSection("release wake-and-unlock");
                releaseBiometricWakeLock();
                Trace.endSection();
            };
    
            if (!delayWakeUp) {
                wakeUp.run();
            }
            switch (mMode) {
                case MODE_DISMISS_BOUNCER:
                    Trace.beginSection("MODE_DISMISS");
                    mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
                            false /* strongAuth */);
                    Trace.endSection();
                    break;
                case MODE_UNLOCK:
                case MODE_SHOW_BOUNCER:
                    Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
                    if (!wasDeviceInteractive) {
                        mPendingShowBouncer = true;
                    } else {
                        showBouncer();
                    }
                    Trace.endSection();
                    break;
                case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
                case MODE_WAKE_AND_UNLOCK_PULSING:
                case MODE_WAKE_AND_UNLOCK:
                    if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
                        Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
                        mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
                                true /* allowEnterAnimation */);
                    } else if (mMode == MODE_WAKE_AND_UNLOCK){
                        Trace.beginSection("MODE_WAKE_AND_UNLOCK");
                    } else {
                        Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
                        mUpdateMonitor.awakenFromDream();
                    }
                    mStatusBarWindowController.setStatusBarFocusable(false);
                    if (delayWakeUp) {
                        mHandler.postDelayed(wakeUp, mWakeUpDelay);
                    } else {
                        mKeyguardViewMediator.onWakeAndUnlocking();
                    }
                    if (mStatusBar.getNavigationBarView() != null) {
                        mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                    }
                    Trace.endSection();
                    break;
                case MODE_ONLY_WAKE:
                case MODE_NONE:
                    break;
            }
            mStatusBar.notifyBiometricAuthModeChanged();
            Trace.endSection();
        }
    
    

    frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

        public void onWakeAndUnlocking() {
            Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking");
            mWakeAndUnlocking = true;
            /*重点关注*/
            keyguardDone();
            Trace.endSection();
        }
    
    

    keyguardDone();

        public void keyguardDone() {
            Trace.beginSection("KeyguardViewMediator#keyguardDone");
            if (DEBUG) Log.d(TAG, "keyguardDone()");
            userActivity();
            EventLog.writeEvent(70000, 2);
            /*重点关注*/
            Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
            mHandler.sendMessage(msg);
            Trace.endSection();
        }
    
    

    KEYGUARD_DONE

                    case KEYGUARD_DONE:
                        Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE");
                        /*重点关注*/
                        handleKeyguardDone();
                        Trace.endSection();
                        break;
    
    

    handleKeyguardDone();

        private void handleKeyguardDone() {
            Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
            final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
            mUiOffloadThread.submit(() -> {
                if (mLockPatternUtils.isSecure(currentUser)) {
                    mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
                }
            });
            if (DEBUG) Log.d(TAG, "handleKeyguardDone");
            synchronized (this) {
                resetKeyguardDonePendingLocked();
            }
    
            mUpdateMonitor.clearBiometricRecognized();
    
            if (mGoingToSleep) {
                Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
                return;
            }
            if (mExitSecureCallback != null) {
                try {
                    mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failed to call onKeyguardExitResult()", e);
                }
    
                mExitSecureCallback = null;
    
                // after succesfully exiting securely, no need to reshow
                // the keyguard when they've released the lock
                mExternallyEnabled = true;
                mNeedToReshowWhenReenabled = false;
                updateInputRestricted();
            }
            /*重点关注*/
            handleHide();
            Trace.endSection();
        }
    
    
    

    handleHide();

        private void handleHide() {
            Trace.beginSection("KeyguardViewMediator#handleHide");
    
            // It's possible that the device was unlocked in a dream state. It's time to wake up.
            if (mAodShowing) {
                PowerManager pm = mContext.getSystemService(PowerManager.class);
                pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                        "com.android.systemui:BOUNCER_DOZING");
            }
    
            synchronized (KeyguardViewMediator.this) {
                if (DEBUG) Log.d(TAG, "handleHide");
    
                if (mustNotUnlockCurrentUser()) {
                    // In split system user mode, we never unlock system user. The end user has to
                    // switch to another user.
                    // TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
                    // still completes and makes the screen blank.
                    if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
                    return;
                }
                mHiding = true;
    
                if (mShowing && !mOccluded) {
                    mKeyguardGoingAwayRunnable.run();
                } else {
                    /*重点关注*/
                    handleStartKeyguardExitAnimation(
                            SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
                            mHideAnimation.getDuration());
                }
            }
            Trace.endSection();
        }
    
    

    handleHide();

        private void handleHide() {
            Trace.beginSection("KeyguardViewMediator#handleHide");
    
            // It's possible that the device was unlocked in a dream state. It's time to wake up.
            if (mAodShowing) {
                PowerManager pm = mContext.getSystemService(PowerManager.class);
                pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                        "com.android.systemui:BOUNCER_DOZING");
            }
    
            synchronized (KeyguardViewMediator.this) {
                if (DEBUG) Log.d(TAG, "handleHide");
    
                if (mustNotUnlockCurrentUser()) {
                    // In split system user mode, we never unlock system user. The end user has to
                    // switch to another user.
                    // TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
                    // still completes and makes the screen blank.
                    if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
                    return;
                }
                mHiding = true;
    
                if (mShowing && !mOccluded) {
                    mKeyguardGoingAwayRunnable.run();
                } else {
                    /*重点关注*/
                    handleStartKeyguardExitAnimation(
                            SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
                            mHideAnimation.getDuration());
                }
            }
            Trace.endSection();
        }
    
    

    handleStartKeyguardExitAnimation

        private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
            Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
            if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
                    + " fadeoutDuration=" + fadeoutDuration);
            synchronized (KeyguardViewMediator.this) {
    
                if (!mHiding) {
                    // Tell ActivityManager that we canceled the keyguardExitAnimation.
                    setShowingLocked(mShowing, mAodShowing, true /* force */);
                    return;
                }
                mHiding = false;
    
                if (mWakeAndUnlocking && mDrawnCallback != null) {
    
                    // Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
                    // the next draw from here so we don't have to wait for window manager to signal
                    // this to our ViewRootImpl.
                    mStatusBarKeyguardViewManager.getViewRootImpl().setReportNextDraw();
                    notifyDrawn(mDrawnCallback);
                    mDrawnCallback = null;
                }
    
                // only play "unlock" noises if not on a call (since the incall UI
                // disables the keyguard)
                if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
                    playSounds(false);
                }
    
                mWakeAndUnlocking = false;
                setShowingLocked(false, mAodShowing);
                mDismissCallbackRegistry.notifyDismissSucceeded();
                /*重点关注*/
                mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
                resetKeyguardDonePendingLocked();
                mHideAnimationRun = false;
                adjustStatusBarLocked();
                sendUserPresentBroadcast();
            }
            Trace.endSection();
        }
    
    

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java

        /**
         * Hides the keyguard view
         */
        public void hide(long startTime, long fadeoutDuration) {
            mShowing = false;
            mKeyguardMonitor.notifyKeyguardState(
                    mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
            launchPendingWakeupAction();
    
            if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
                fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
            }
            long uptimeMillis = SystemClock.uptimeMillis();
            long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
    
            if (mStatusBar.isInLaunchTransition() ) {
                mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
                    @Override
                    public void run() {
                        mStatusBarWindowController.setKeyguardShowing(false);
                        mStatusBarWindowController.setKeyguardFadingAway(true);
                        hideBouncer(true /* destroyView */);
                        updateStates();
                    }
                }, new Runnable() {
                    @Override
                    public void run() {
                        mStatusBar.hideKeyguard();
                        mStatusBarWindowController.setKeyguardFadingAway(false);
                        mViewMediatorCallback.keyguardGone();
                        executeAfterKeyguardGoneAction();
                    }
                });
            } else {
                executeAfterKeyguardGoneAction();
                boolean wakeUnlockPulsing =
                        mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
                if (wakeUnlockPulsing) {
                    delay = 0;
                    fadeoutDuration = 240;
                }
                mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
                mBiometricUnlockController.startKeyguardFadingAway();
                /*重点关注*/
                hideBouncer(true /* destroyView */);
                if (wakeUnlockPulsing) {
                    mStatusBar.fadeKeyguardWhilePulsing();
                    wakeAndUnlockDejank();
                } else {
                    boolean staying = mStatusBar.hideKeyguard();
                    if (!staying) {
                        mStatusBarWindowController.setKeyguardFadingAway(true);
                        // hide() will happen asynchronously and might arrive after the scrims
                        // were already hidden, this means that the transition callback won't
                        // be triggered anymore and StatusBarWindowController will be forever in
                        // the fadingAway state.
                        mStatusBar.updateScrimController();
                        wakeAndUnlockDejank();
                    } else {
                        mStatusBar.finishKeyguardFadingAway();
                        mBiometricUnlockController.finishKeyguardFadingAway();
                    }
                }
                updateStates();
                mStatusBarWindowController.setKeyguardShowing(false);
                mViewMediatorCallback.keyguardGone();
            }
            StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
                StatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
        }
    
    

    hideBouncer

        private void hideBouncer(boolean destroyView) {
            if (mBouncer == null) {
                return;
            }
            /*重点关注*/
            mBouncer.hide(destroyView);
            cancelPendingWakeupAction();
        }
    
    

    frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java

        public void hide(boolean destroyView) {
            if (isShowing()) {
                StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
                    StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
                mDismissCallbackRegistry.notifyDismissCancelled();
            }
            mIsScrimmed = false;
            mFalsingManager.onBouncerHidden();
            mCallback.onBouncerVisiblityChanged(false /* shown */);
            cancelShowRunnable();
            if (mKeyguardView != null) {
                mKeyguardView.cancelDismissAction();
                mKeyguardView.cleanUp();
            }
            mIsAnimatingAway = false;
            if (mRoot != null) {
                mRoot.setVisibility(View.INVISIBLE);
                if (destroyView) {
    
                    // We have a ViewFlipper that unregisters a broadcast when being detached, which may
                    // be slow because of AM lock contention during unlocking. We can delay it a bit.
                    /*重点关注*/
                    mHandler.postDelayed(mRemoveViewRunnable, 50);
                }
            }
        }
    
    

    mRemoveViewRunnable

    private final Runnable mRemoveViewRunnable = this::removeView;
        protected void removeView() {
            if (mRoot != null && mRoot.getParent() == mContainer) {
                /*重点关注*/
                mContainer.removeView(mRoot);
                mRoot = null;
            }
        }
    
    

    至此锁屏界面移除的逻辑基本clear
    原文链接:https://blog.csdn.net/Easyhood/article/details/104353983

    至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

    相关文章

      网友评论

          本文标题:Android 人脸解锁源码剖析

          本文链接:https://www.haomeiwen.com/subject/zrdsiltx.html