Android 8.0指纹流程


第一部分 指纹模块流程分析

一、Fingerprint模块架构

Fingerprint模块架构主要由application,framework,fingerprintd和FingerprintHal这几个部分,以及涉及到指纹的IC库和驱动这部分,这部分逻辑由指纹厂商来实现。 

application层主要涉及到Settings 和 SystemUI


二、指纹录入

1.Settings中重要的指纹相关类

FingerprintEnrollBase.java 指纹录制的基类

FingerprintEnrollFindSensor.java  指纹开始准备录入的activity,继承FingerprintEnrollBase

FingerprintEnrollSidecar.java  注册EnrollmentCallback,监听指纹录入状态,在FingerprintEnrollFindSensor中会new FingerprintEnrollSidecar

FingerprintFindSensorAnimation.java  指纹动画接口

FingerprintLocationAnimationView.java 指纹动画,实现了FingerprintFindSensorAnimation接口

FingerprintEnrollFinish.java 指纹录制结束的activity,同样继承FingerprintEnrollBase

FingerprintEnrollEnrolling.java  指纹正在录制的activity,同样继承FingerprintEnrollBase,同样也 new 

FingerprintRemoveSidecar.java 管理指纹删除操作

FingerprintEnrollSidecar() 管理指纹录入


2.准备录入指纹

启动FingerprintEnrollFindSensor(开始准备录入指纹的activity)时,在onCreate()中调用startLookingForFingerprint(),

new FingerprintEnrollSidecar() --->onStart() --->startEnrollment()--->mFingerprintManager.enroll()

FingerprintManager.java  --- enroll()

    @RequiresPermission(MANAGE_FINGERPRINT)
    public void enroll(byte [] token, CancellationSignal cancel, int flags,
            int userId, EnrollmentCallback callback) {
        if (userId == UserHandle.USER_CURRENT) {
            userId = getCurrentUserId();
        }
        if (callback == null) {
            throw new IllegalArgumentException("Must supply an enrollment callback");
        }

        if (cancel != null) {
            if (cancel.isCanceled()) {
                Log.w(TAG, "enrollment already canceled");
                return;
            } else {
                cancel.setOnCancelListener(new OnEnrollCancelListener());
            }
        }

        if (mService != null) try {
            mEnrollmentCallback = callback;
            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
                    mContext.getOpPackageName());
        } 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(FINGERPRINT_ERROR_HW_UNAVAILABLE,
                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
            }
        }
    }


FingerprintService.java--- enroll()

        @Override // Binder call
        public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
                final IFingerprintServiceReceiver receiver, final int flags,
                final String opPackageName) {
            checkPermission(MANAGE_FINGERPRINT);
            final int limit =  mContext.getResources().getInteger(
                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);

            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
            if (enrolled >= limit) {
                Slog.w(TAG, "Too many fingerprints registered");
                return;
            }

            // Group ID is arbitrarily set to parent profile user ID. It just represents
            // the default fingerprints for the user.
            if (!isCurrentUserOrProfile(userId)) {
                return;
            }

            final boolean restricted = isRestricted();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startEnrollment(token, cryptoToken, userId, receiver, flags,
                            restricted, opPackageName);
                }
            });
        }
    private void startEnrollment(IBinder token, byte [] cryptoToken, int userId,
            IFingerprintServiceReceiver receiver, int flags, boolean restricted,
            String opPackageName) {
        updateActiveGroup(userId, opPackageName);

        final int groupId = userId; // default group for fingerprint enrollment

        EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver,
                userId, groupId, cryptoToken, restricted, opPackageName) {

            @Override
            public IBiometricsFingerprint getFingerprintDaemon() {
                return FingerprintService.this.getFingerprintDaemon();
            }

            @Override
            public void notifyUserActivity() {
                FingerprintService.this.userActivity();
            }
        };
        startClient(client, true /* initiatedByClient */);
    }
    private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
        ClientMonitor currentClient = mCurrentClient;
        if (currentClient != null) {
            if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
            if (currentClient instanceof InternalEnumerateClient ||
                    currentClient instanceof InternalRemovalClient) {
                // This condition means we're currently running internal diagnostics to
                // remove extra fingerprints in the hardware and/or the software
                // TODO: design an escape hatch in case client never finishes
            }
            else {
                currentClient.stop(initiatedByClient);
            }
            mPendingClient = newClient;
            mHandler.removeCallbacks(mResetClientState);
            mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
        } else if (newClient != null) {
            mCurrentClient = newClient;
            if (DEBUG) Slog.v(TAG, "starting client "
                    + newClient.getClass().getSuperclass().getSimpleName()
                    + "(" + newClient.getOwnerString() + ")"
                    + ", initiatedByClient = " + initiatedByClient + ")");
            notifyClientActiveCallbacks(true);


            newClient.start();
    }

startEnrollment方法中会调用EnrollClient的start方法,EnrollClient是为给定的客户端跟踪指纹录制状态。

/**
 * A class to keep track of the enrollment state for a given client.
 */
public abstract class EnrollClient extends ClientMonitor {
    ......
    public EnrollClient(Context context, long halDeviceId, IBinder token,
            IFingerprintServiceReceiver receiver, int userId, int groupId, byte [] cryptoToken,
            boolean restricted, String owner) {
        super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
        ......
    }

    @Override
    public boolean onEnrollResult(int fingerId, int groupId, int remaining) {
       if (remaining == 0) {
            FingerprintUtils.getInstance().addFingerprintForUser(getContext(), fingerId,
                    getTargetUserId());
        }
        return sendEnrollResult(fingerId, groupId, remaining);
    }

    /*
     * @return true if we're done.
     */
    private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
        IFingerprintServiceReceiver receiver = getReceiver();
            ......
            receiver.onEnrollResult(getHalDeviceId(), fpId, groupId, remaining);
            ......
    }

    @Override
    public int start() {
        IFingerprintDaemon daemon = getFingerprintDaemon();
            ......
            final int result = daemon.enroll(mCryptoToken, getGroupId(), timeout);
            ......
        return 0; // success
    }

start方法会调用fingerprintd,调用底层的指纹库,底层库返回结果后会调用onEnrollResult来反馈结果给receiver,在往上层反馈。这就是指纹的录制流程。在onEnrollResult中当remaining等于0的时候录制完成,调用addFingerprintForUser()

FingerprintManager.java中注册了IFingerprintServiceReceiver,实现onEnrollResult方法发送MSG_ENROLL_RESULT

private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {

        @Override // binder call
        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
        }

        @Override // binder call
        public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode, deviceId).sendToTarget();
        }

        @Override // binder call
        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
        }

        @Override // binder call
        public void onAuthenticationFailed(long deviceId) {
            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
        }

        @Override // binder call
        public void onError(long deviceId, int error, int vendorCode) {
            mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
        }

        @Override // binder call
        public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
            mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
        }

        @Override // binder call
        public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
            // TODO: propagate remaining
            mHandler.obtainMessage(MSG_ENUMERATED, fingerId, groupId, deviceId).sendToTarget();
        }
    };
        @Override
        public void handleMessage(android.os.Message msg) {
            switch(msg.what) {
                case MSG_ENROLL_RESULT:
                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                    break;

调用回调方法

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

EnrollmentCallback是FingerprintManager.java的抽象内部类

public static abstract class EnrollmentCallback {
        /**
         * Called when an unrecoverable error has been encountered and the operation is complete.
         * No further callbacks will be made on this object.
         * @param errMsgId An integer identifying the error message
         * @param errString A human-readable error string that can be shown in UI
         */
        public void onEnrollmentError(int errMsgId, CharSequence errString) { }

        /**
         * Called when a recoverable error has been encountered during enrollment. The help
         * string is provided to give the user guidance for what went wrong, such as
         * "Sensor dirty, please clean it" or what they need to do next, such as
         * "Touch sensor again."
         * @param helpMsgId An integer identifying the error message
         * @param helpString A human-readable string that can be shown in UI
         */
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }

        /**
         * Called as each enrollment step progresses. Enrollment is considered complete when
         * remaining reaches 0. This function will not be called if enrollment fails. See
         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
         * @param remaining The number of remaining steps
         */
        public void onEnrollmentProgress(int remaining) { }
    };


再回过头来看Settings

FingerprintEnrollSidecar.java中注册EnrollmentCallback,监听指纹录入状态。并写有一个内部接口Listener

    public interface Listener {        
        void onEnrollmentHelp(int helpMsgId,CharSequence helpString);
        //void onEnrollmentHelp(CharSequence helpString);       
        void onEnrollmentError(int errMsgId, CharSequence errString);
        void onEnrollmentProgressChange(int steps, int remaining);
    }

一个public方法

    public void setListener(Listener listener) {
        mListener = listener;
        ......
    }

实现了EnrollmentCallback接口

 private FingerprintManager.EnrollmentCallback mEnrollmentCallback
            = new FingerprintManager.EnrollmentCallback() {

        @Override
        public 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));
            }
        }

        @Override
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
            if (mListener != null) {
                mListener.onEnrollmentHelp(helpMsgId,helpString);
                //mListener.onEnrollmentHelp(helpString);
            } else {
                mQueuedEvents.add(new QueuedEnrollmentHelp(helpMsgId, helpString));
            }
        }

        @Override
        public void onEnrollmentError(int errMsgId, CharSequence errString) {
            if (mListener != null) {
                mListener.onEnrollmentError(errMsgId, errString);
            } else {
                mQueuedEvents.add(new QueuedEnrollmentError(errMsgId, errString));
            }
            mEnrolling = false;
        }
    };

FingerprintEnrollFindSensor.java和FingerprintEnrollEnrolling.java 分别implements FingerprintEnrollSidecar.Listener,从而实现了CallBack

三,指纹重命名


弹出重命名框:FingerprintSettings.java--->RenameDialog--->renameFingerPrint()

调用到FingerprintManager.java的rename()方法

    @RequiresPermission(MANAGE_FINGERPRINT)
    public void rename(int fpId, int userId, String newName) {
        // Renames the given fpId
        if (mService != null) {
            try {
                mService.rename(fpId, userId, newName);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } else {
            Log.w(TAG, "rename(): Service not connected!");
        }
调用FingerprintService.java的rename()方法
        @Override // Binder call
        public void rename(final int fingerId, final int groupId, final String name) {
            checkPermission(MANAGE_FINGERPRINT);
            if (!isCurrentUserOrProfile(groupId)) {
                return;
            }
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
                            groupId, name);
                }
            });
        }
再到FingerprintUtils.java的renameFingerprintForUser()
    public void renameFingerprintForUser(Context ctx, int fingerId, int userId, CharSequence name) {
        if (TextUtils.isEmpty(name)) {
            // Don't do the rename if it's empty
            return;
        }
        getStateForUser(ctx, userId).renameFingerprint(fingerId, name);
    }
到FingerprintsUserState的renameFingerprint()
    public void renameFingerprint(int fingerId, CharSequence name) {
        synchronized (this) {
            for (int i = 0; i < mFingerprints.size(); i++) {
                if (mFingerprints.get(i).getFingerId() == fingerId) {
                    Fingerprint old = mFingerprints.get(i);
                    mFingerprints.set(i, new Fingerprint(name, old.getGroupId(), old.getFingerId(),
                            old.getDeviceId()));
                    scheduleWriteStateLocked();
                    break;
                }
            }
        }
    }

四,指纹的删除流程

弹出删除确认框FingerprintSettings.java--->DeleteFingerprintDialog--->deleteFingerPrint()

        void deleteFingerPrint(Fingerprint fingerPrint) {
            mRemovalSidecar.startRemove(fingerPrint, mUserId);
            String name = genKey(fingerPrint.getFingerId());
            Preference prefToRemove = findPreference(name);
            prefToRemove.setEnabled(false);
            updateAddPreference();
        }

调用FingerprintRemoveSidecar.java的startRemove()

    public void startRemove(Fingerprint fingerprint, int userId) {
        if (mFingerprintRemoving != null) {
            Log.e(TAG, "Remove already in progress");
            return;
        }
        if (userId != UserHandle.USER_NULL) {
            mFingerprintManager.setActiveUser(userId);
        }
        mFingerprintRemoving = fingerprint;
        mFingerprintManager.remove(fingerprint, userId, mRemoveCallback);;
    }

可以看到调用FingerprintManager的remove方法时传入了一个removeCallback,看下这个Callbcak

    private FingerprintManager.RemovalCallback
            mRemoveCallback = new FingerprintManager.RemovalCallback() {
        @Override
        public void onRemovalSucceeded(Fingerprint fingerprint, int remaining) {
            if (mListener != null) {
                mListener.onRemovalSucceeded(fingerprint);
            } else {
                mFingerprintsRemoved.add(fingerprint);
            };
            mFingerprintRemoving = null;
        }

        @Override
        public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) {
            if (mListener != null) {
                mListener.onRemovalError(fp, errMsgId, errString);
            } else {
                mFingerprintsRemoved.add(new RemovalError(fp, errMsgId, errString));
            }
            mFingerprintRemoving = null;
        }
    };

这个Listener是FingerprintRemoveSidecar的一个内部接口,FingerprintSettings实现了这个接口

    public interface Listener {
        void onRemovalSucceeded(Fingerprint fingerprint);
        void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString);
    }

回过头来继续看FingerprintManager的remove方法

    public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
        if (mService != null) try {
            mRemovalCallback = callback;
            mRemovalFingerprint = fp;
            mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
        } catch (RemoteException e) {
            Log.w(TAG, "Remote exception in remove: ", e);
            if (callback != null) {
                callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
            }
        }
    }

调用FingerprintService的remove方法

        public void remove(final IBinder token, final int fingerId, final int groupId,
                final int userId, final IFingerprintServiceReceiver receiver) {
            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
            final boolean restricted = isRestricted();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startRemove(token, fingerId, groupId, userId, receiver,
                            restricted, false /* internal */);
                }
            });
        }
FingerprintService--->startRemove
void startRemove(IBinder token, int fingerId, int groupId, int userId,
            IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
        IBiometricsFingerprint daemon = getFingerprintDaemon();
        if (daemon == null) {
            Slog.w(TAG, "startRemove: no fingerprint HAL!");
            return;
        }

        if (internal) {
            Context context = getContext();
            InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
                    token, receiver, fingerId, groupId, userId, restricted,
                    context.getOpPackageName()) {
                @Override
                public void notifyUserActivity() {

                }
                @Override
                public IBiometricsFingerprint getFingerprintDaemon() {
                    return FingerprintService.this.getFingerprintDaemon();
                }
            };
            startClient(client, true);
        }//internal是false,所以调用RemovalClient
        else {
            RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
                    receiver, fingerId, groupId, userId, restricted, token.toString()) {
                @Override
                public void notifyUserActivity() {
                    FingerprintService.this.userActivity();
                }

                @Override
                public IBiometricsFingerprint getFingerprintDaemon() {
                    return FingerprintService.this.getFingerprintDaemon();
                }
            };
            startClient(client, true);
        }
    }

RemovalClient和EnrollClient一样都是继承ClientMonitor,start方法会调用fingerprintd,调用底层的指纹库,底层库返回结果后会调用onEnrollResult来反馈结果给onRemoved,在往上层反馈。这就是指纹的删除流程

    @Override
    public boolean onRemoved(int fingerId, int groupId, int remaining) {
        if (fingerId != 0) {
            FingerprintUtils.getInstance().removeFingerprintIdForUser(getContext(), fingerId,
                    getTargetUserId());
        }
        return sendRemoved(fingerId, getGroupId(), remaining);
    }

FingerprintUtils --->removeFingerprintIdForUser

    public void removeFingerprintIdForUser(Context ctx, int fingerId, int userId) {
        getStateForUser(ctx, userId).removeFingerprint(fingerId);
    }

FingerprintsUserState --->removeFingerprint

    public void removeFingerprint(int fingerId) {
        synchronized (this) {
            for (int i = 0; i < mFingerprints.size(); i++) {
                if (mFingerprints.get(i).getFingerId() == fingerId) {
                    mFingerprints.remove(i);
                    scheduleWriteStateLocked();
                    break;
                }
            }
        }
    }


五,指纹解锁流程

首先分析下灭屏后,如何开始监听指纹解锁的

灭屏后会走到PhoneWindowManager.java-->startedGoingToSleep()方法

    // Called on the PowerManager's Notifier thread.
    @Override
    public void startedGoingToSleep(int why) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");

        mGoingToSleep = true;
        mRequestedOrGoingToSleep = true;

        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onStartedGoingToSleep(why);
        }
    }

KeyguardServiceDelegate.java-->onStartedGoingToSleep()

    public void onStartedGoingToSleep(int why) {
        if (mKeyguardService != null) {
            mKeyguardService.onStartedGoingToSleep(why);
        }
        mKeyguardState.offReason = why;
        mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
    }

KeyguardServiceWrapper.java-->onStartedGoingToSleep()

    @Override
    public void onStartedGoingToSleep(int reason) {
        try {
            mService.onStartedGoingToSleep(reason);
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }

KeyguardService.java-->onStartedGoingToSleep()

        @Override // Binder interface
        public void onStartedGoingToSleep(int reason) {
            checkPermission();
            mKeyguardViewMediator.onStartedGoingToSleep(reason);
            mKeyguardLifecyclesDispatcher.dispatch(
                    KeyguardLifecyclesDispatcher.STARTED_GOING_TO_SLEEP);
        }

KeyguardViewMediator.java-->onStartedGoingToSleep()

public void onStartedGoingToSleep(int why) {
      ......
        KeyguardUpdateMonitor.getInstance(mContext).dispatchStartedGoingToSleep(why);
        notifyStartedGoingToSleep();
}

KeyguardUpdateMonitor.java-->dispatchStartedGoingToSleep()

    public void dispatchStartedGoingToSleep(int why) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0));
    }
                case MSG_STARTED_GOING_TO_SLEEP:
                    handleStartedGoingToSleep(msg.arg1);
                    break;

KeyguardUpdateMonitor.java-->handleStartedGoingToSleep()

    protected void handleStartedGoingToSleep(int arg1) {
        clearFingerprintRecognized();
        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;
        updateFingerprintListeningState();
    }

KeyguardUpdateMonitor.java-->updateFingerprintListeningState()

    private void updateFingerprintListeningState() {
        // If this message exists, we should not authenticate again until this message is
        // consumed by the handler
        if (mHandler.hasMessages(MSG_FINGERPRINT_AUTHENTICATION_CONTINUE)) {
            return;
        }
        mHandler.removeCallbacks(mRetryFingerprintAuthentication);
        boolean shouldListenForFingerprint = shouldListenForFingerprint();
        if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
            stopListeningForFingerprint();
        } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
                && shouldListenForFingerprint) {
            startListeningForFingerprint();
        }
    }

KeyguardUpdateMonitor.java-->startListeningForFingerprint()

    private void startListeningForFingerprint() {
        if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
            setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
            return;
        }
        if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
        int userId = ActivityManager.getCurrentUser();
        if (isUnlockWithFingerprintPossible(userId)) {
            if (mFingerprintCancelSignal != null) {
                mFingerprintCancelSignal.cancel();
            }
            mFingerprintCancelSignal = new CancellationSignal();
            mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
            setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
        }
    }

FingerprintManager.java-->authenticate()

    @RequiresPermission(USE_FINGERPRINT)
    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 (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;
            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(FINGERPRINT_ERROR_HW_UNAVAILABLE,
                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
            }
        }
    }

FingerprintService.java-->authenticate()

@Override // Binder call
        public void authenticate(final IBinder token, final long opId, final int groupId,
                final IFingerprintServiceReceiver receiver, final int flags,
                final String opPackageName) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int callingUserId = UserHandle.getCallingUserId();
            final boolean restricted = isRestricted();

            if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
                    callingUserId)) {
                if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
                return;
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    MetricsLogger.histogram(mContext, "fingerprint_token", 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;

                    startAuthentication(token, opId, callingUserId, groupId, receiver,
                            flags, restricted, opPackageName);
                }
            });
        }

FingerprintService.java-->startAuthentication()

    private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
                IFingerprintServiceReceiver receiver, int flags, boolean restricted,
                String opPackageName) {
        updateActiveGroup(groupId, opPackageName);

        if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");

        AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
                receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
            @Override
            public int handleFailedAttempt() {
                mFailedAttempts++;
                mTimedLockoutCleared = false;
                final int lockoutMode = getLockoutMode();
                if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
                    mPerformanceStats.permanentLockout++;
                } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
                    mPerformanceStats.lockout++;
                }
                // Failing multiple times will continue to push out the lockout time
                if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
                    scheduleLockoutReset();
                    return lockoutMode;
                }
                return AuthenticationClient.LOCKOUT_NONE;
            }

            @Override
            public void resetFailedAttempts() {
                FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */);
            }

            @Override
            public void notifyUserActivity() {
                FingerprintService.this.userActivity();
            }

            @Override
            public IBiometricsFingerprint getFingerprintDaemon() {
                return FingerprintService.this.getFingerprintDaemon();
            }
        };

        int lockoutMode = getLockoutMode();
        if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
            Slog.v(TAG, "In lockout mode(" + lockoutMode +
                    ") ; disallowing authentication");
            int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
            if (!client.onError(errorCode, 0 /* vendorCode */)) {
                Slog.w(TAG, "Cannot send permanent lockout message to client");
            }
            return;
        }
        startClient(client, true /* initiatedByClient */);
    }

灭屏时开始监听的流程完成,当有指纹解锁时,会执行

AuthenticationClient.java-->onAuthenticated()

@Override
public boolean onAuthenticated(int fingerId, int groupId) {
    ......
    IFingerprintServiceReceiver receiver = getReceiver();
    ......
    receiver.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId());
}

FingerprintManager.java-->new IFingerprintServiceReceiver.Stub()-->onAuthenticationSucceeded()

private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
        @Override // binder call
        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
        }

        @Override // binder call
        public void onAuthenticationFailed(long deviceId) {
            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
        }
}
                case MSG_AUTHENTICATION_SUCCEEDED:
                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
                    break;

FingerprintManager.java-->sendAuthenticatedSucceeded()

        private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
            if (mAuthenticationCallback != null) {
                final AuthenticationResult result =
                        new AuthenticationResult(mCryptoObject, fp, userId);
                mAuthenticationCallback.onAuthenticationSucceeded(result);
            }
        }

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

public static abstract class 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 fingerprint is recognized.
         * @param result An object containing authentication-related data
         */
        public void onAuthenticationSucceeded(AuthenticationResult result) { }

        /**
         * Called when a fingerprint is valid but not recognized.
         */
        public void onAuthenticationFailed() { }

        /**
         * Called when a fingerprint image has been acquired, but wasn't processed yet.
         *
         * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
         * @hide
         */
        public void onAuthenticationAcquired(int acquireInfo) {}
    };

此接口在KeyguardUpdateMonitor.java中实现,用于监听FingerprintService中的指纹解锁状态

    private FingerprintManager.AuthenticationCallback mAuthenticationCallback
            = new AuthenticationCallback() {

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

        @Override
        public void onAuthenticationSucceeded(AuthenticationResult result) {
            Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
            handleFingerprintAuthenticated(result.getUserId());
            Trace.endSection();
        }

        @Override
        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
            handleFingerprintHelp(helpMsgId, helpString.toString());
        }

        @Override
        public void onAuthenticationError(int errMsgId, CharSequence errString) {
            handleFingerprintError(errMsgId, errString.toString());
        }

        @Override
        public void onAuthenticationAcquired(int acquireInfo) {
            handleFingerprintAcquired(acquireInfo);
        }
    };

KeyguardUpdateMonitor.java-->handleFingerprintAuthenticated()

    private void handleFingerprintAuthenticated(int authUserId) {
        Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
        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, "Fingerprint authenticated for wrong user: " + authUserId);
                return;
            }
            if (isFingerprintDisabled(userId)) {
                Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
                return;
            }
            onFingerprintAuthenticated(userId);
        } finally {
            setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
        }
        Trace.endSection();
    }

KeyguardUpdateMonitor.java-->onFingerprintAuthenticated()

private void onFingerprintAuthenticated(int userId) {
        Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
        mUserFingerprintAuthenticated.put(userId, true);
        // Update/refresh trust state only if user can skip bouncer
        if (getUserCanSkipBouncer(userId)) {
            mTrustManager.unlockedByFingerprintForUser(userId);
        }
        // Don't send cancel if authentication succeeds
        mFingerprintCancelSignal = null;
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onFingerprintAuthenticated(userId);
            }
        }

        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATION_CONTINUE),
                FINGERPRINT_CONTINUE_DELAY_MS);

        // Only authenticate fingerprint once when assistant is visible
        mAssistantVisible = false;

        Trace.endSection();
    }

可以看到在onFingerprintAuthenticated()方法中调用了KeyguardUpdateMonitorCallback这个抽象类的onFingerprintAuthenticated()抽象方法,

而FingerprintUnlockController extends KeyguardUpdateMonitorCallback,并注册了回调mUpdateMonitor.registerCallback(this);

所以会调用到

FingerprintUnlockController.java-->onFingerprintAuthenticated()

    @Override
    public void onFingerprintAuthenticated(int userId) {
        Trace.beginSection("FingerprintUnlockController#onFingerprintAuthenticated");
        if (mUpdateMonitor.isGoingToSleep()) {
            mPendingAuthenticatedUserId = userId;
            Trace.endSection();
            return;
        }
        startWakeAndUnlock(calculateMode());
    }

FingerprintUnlockController.java-->startWakeAndUnlock()

    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.
            mStatusBarWindowManager.setForceDozeBrightness(true);
        }
        if (!wasDeviceInteractive) {
            if (DEBUG_FP_WAKELOCK) {
                Log.i(TAG, "fp wakelock: Authenticated, waking up...");
            }
            mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
        }
        Trace.beginSection("release wake-and-unlock");
        releaseFingerprintWakeLock();
        Trace.endSection();
        switch (mMode) {
            case MODE_DISMISS_BOUNCER:
                Trace.beginSection("MODE_DISMISS");
                mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
                        false /* strongAuth */);
                Trace.endSection();
                break;
            case MODE_UNLOCK:
            case MODE_SHOW_BOUNCER:
                boolean unlockingAllowed = mUpdateMonitor.getUserCanSkipBouncer(
                                                mUpdateMonitor.getCurrentUser());
                //for qq start
                if(unlockingAllowed && mStatusBarKeyguardViewManager.isOccluded()){
                    mKeyguardViewMediator.keyguardDone();
                } else {
                    Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
                    if (!wasDeviceInteractive) {
                        mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
                        mPendingShowBouncer = true;
                    } else {
                        showBouncer();
                    }
                    Trace.endSection();
                }
                //for qq end
                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");
                    mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
                            true /* allowEnterAnimation */);
                } else if (mMode == MODE_WAKE_AND_UNLOCK){
                    Trace.beginSection("MODE_WAKE_AND_UNLOCK");
                    mDozeScrimController.abortDoze();
                } else {
                    Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
                    mUpdateMonitor.awakenFromDream();
                }
                mStatusBarWindowManager.setStatusBarFocusable(false);
                mKeyguardViewMediator.onWakeAndUnlocking();
                mScrimController.setWakeAndUnlocking();
                mDozeScrimController.setWakeAndUnlocking();
                if (mStatusBar.getNavigationBarView() != null) {
                    mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                }
                Trace.endSection();
                break;
            case MODE_ONLY_WAKE:
            case MODE_NONE:
                break;
        }
        mStatusBar.notifyFpAuthModeChanged();
        Trace.endSection();
    }

KeyguardViewMediator.java-->onWakeAndUnlocking()

    public void onWakeAndUnlocking() {
        Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking");
        mWakeAndUnlocking = true;
        keyguardDone();
        Trace.endSection();
    }

KeyguardViewMediator.java-->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();
    }
                case KEYGUARD_DONE:
                    Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE");
                    handleKeyguardDone();
                    Trace.endSection();
                    break;

KeyguardViewMediator.java-->handleKeyguardDone()

private void handleKeyguardDone() {
     ......
     handleHide();
}

KeyguardViewMediator.java-->handleHide()

    private void handleHide() {
        Trace.beginSection("KeyguardViewMediator#handleHide");
        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();
    }

KeyguardViewMediator.java-->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) {
                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)
            ///M: fix ALPS01933919 to avoid play unlock sound continuously.
            ///   also fixes ALPS01940830
            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) && mShowing) {
                playSounds(false);
            }

            mWakeAndUnlocking = false;
            setShowingLocked(false);
            mDismissCallbackRegistry.notifyDismissSucceeded();
            mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            adjustStatusBarLocked();
            sendUserPresentBroadcast();
            mUpdateMonitor.setKeyguardGoingAway(false /* goingAway */);
        }

        Log.d(TAG, "set mKeyguardDoneOnGoing = false");
        mKeyguardDoneOnGoing = false;
        Trace.endSection();
    }
StatusBarKeyguardViewManager.java-->hide()

   /**
     * Hides the keyguard view
     */
    public void hide(long startTime, long fadeoutDuration) {
        mShowing = false;
        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() {
                    mStatusBarWindowManager.setKeyguardShowing(false);
                    mStatusBarWindowManager.setKeyguardFadingAway(true);
                    hideBouncer(true /* destroyView */);
                    updateStates();
                    mScrimController.animateKeyguardFadingOut(
                            StatusBar.FADE_KEYGUARD_START_DELAY,
                            StatusBar.FADE_KEYGUARD_DURATION, null,
                            false /* skipFirstFrame */);
                }
            }, new Runnable() {
                @Override
                public void run() {
                    mStatusBar.hideKeyguard();
                    mStatusBarWindowManager.setKeyguardFadingAway(false);
                    mViewMediatorCallback.keyguardGone();
                    executeAfterKeyguardGoneAction();
                }
            });
        } else {
           executeAfterKeyguardGoneAction();
            boolean wakeUnlockPulsing =
                    mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
            if (wakeUnlockPulsing) {
                delay = 0;
                fadeoutDuration = 240;
            }
            mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
            mFingerprintUnlockController.startKeyguardFadingAway();
            hideBouncer(true /* destroyView */);
            if (wakeUnlockPulsing) {
                mStatusBarWindowManager.setKeyguardFadingAway(true);
                mStatusBar.fadeKeyguardWhilePulsing();
                animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
                        mStatusBar::hideKeyguard, false /* skipFirstFrame */);
            } else {
                mFingerprintUnlockController.startKeyguardFadingAway();
                mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
                boolean staying = mStatusBar.hideKeyguard();
                if (!staying) {
                    mStatusBarWindowManager.setKeyguardFadingAway(true);
                    if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK) {
                        boolean turnedOnSinceAuth =
                                mFingerprintUnlockController.hasScreenTurnedOnSinceAuthenticating();
                        if (!mScreenTurnedOn || mDisplayBlanksAfterDoze && !turnedOnSinceAuth) {
                            // Not ready to animate yet; either because the screen is not on yet,
                            // or it is on but will turn off before waking out of doze.
                            mDeferScrimFadeOut = true;
                        } else {

                            // Screen is already on, don't defer with fading out.
                            animateScrimControllerKeyguardFadingOut(0,
                                    WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
                                    true /* skipFirstFrame */);
                        }
                    } else {
                        animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
                                false /* skipFirstFrame */);
                    }
                } else {
                    mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
                    mStatusBar.finishKeyguardFadingAway();
                    mFingerprintUnlockController.finishKeyguardFadingAway();
                }
            }
            updateStates();
            mStatusBarWindowManager.setKeyguardShowing(false);
            mViewMediatorCallback.keyguardGone();
        }
    }

StatusBarKeyguardViewManager.java-->hideBouncer()

    private void hideBouncer(boolean destroyView) {
        mBouncer.hide(destroyView);
        cancelPendingWakeupAction();
    }

KeyguardBouncer.java-->hide()

    public void hide(boolean destroyView) {
        if (isShowing()) {
            mDismissCallbackRegistry.notifyDismissCancelled();
        }
        mFalsingManager.onBouncerHidden();
        cancelShowRunnable();
        if (mKeyguardView != null) {
            mKeyguardView.cancelDismissAction();
            mKeyguardView.cleanUp();
        }
        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);
            }
        }
    }
 private final Runnable mRemoveViewRunnable = this::removeView;

KeyguardBouncer.java-->removeView()

    protected void removeView() {
        if (mRoot != null && mRoot.getParent() == mContainer) {
            mContainer.removeView(mRoot);
            mRoot = null;
        }
    }



猜你喜欢

转载自blog.csdn.net/liu362732346/article/details/80082409