Android N指纹识别

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

一、Fingerprint模块架构

Fingerprint模块架构图如下,这里分为application,framework,fingerprintd和FingerprintHal这几个部分,不涉及指纹的IC库和驱动这部分,这部分逻辑由指纹厂商来实现。 
这里写图片描述

Setting中指纹代码

这里写图片描述

SystemUI中指纹解锁代码

这里写图片描述

二、Fingerprint framework初始化流程

在系统开机的时候,会启动各种Service,包括FingerprintService。从下图的开机log(sys_log.boot)中可以看出:

05-29 10:37:57.870869  1127  1127 I SystemServiceManager: Starting com.android.server.dreams.DreamManagerService
05-29 10:37:57.874643  1127  1127 I SystemServer: StartAssetAtlasService
05-29 10:37:57.883240  1127  1127 I SystemServiceManager: Starting com.android.server.print.PrintManagerService
05-29 10:37:57.910104  1127  1127 I SystemServiceManager: Starting com.android.server.restrictions.RestrictionsManagerService
05-29 10:37:57.913926  1127  1127 I SystemServiceManager: Starting com.android.server.media.MediaSessionService
05-29 10:37:57.926584  1127  1127 I SystemServer: StartMediaRouterService
05-29 10:37:57.939619  1127  1127 I SystemServiceManager: Starting com.android.server.trust.TrustManagerService
05-29 10:37:57.952689  1127  1127 I SystemServiceManager: Starting com.android.server.fingerprint.FingerprintService
05-29 10:37:58.866228  1127  1127 V FingerprintService: Fingerprint HAL id: 488345235968
05-29 10:37:58.867305  1127  1127 I SystemServer: StartBackgroundDexOptService

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

FingerprintService的启动在SystemServer.Java的startOtherService方法中

/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
   final Context context = mSystemContext;
   VibratorService vibrator = null;
   IMountService mountService = null;
   .......
   //启动FingerprintService
   if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
       mSystemServiceManager.startService(FingerprintService.class);
   }
        ......

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这里启动的时候,会将FingerprintService添加到ServiceManager中去,如下图: 
这里写图片描述
将FingerprintService添加到ServiceManager中后,在SystemServiceRegistry.java中静态代码块中注册服务的时候,可以从ServiceManager中获取FingerprintService的Binder对象,从而可以构造出FingerprintManager对象,这样app端就可以通过Context来获取FingerprintManager对象。另外FingerprintService的onStart()方法中还会调用getFingerprintDaemon()来完成以下步骤:

//①获取fingerprintd
//②向fingerprintd注册回调函数mDaemonCallback
//③调用获取fingerprintd的openhal函数
public IFingerprintDaemon getFingerprintDaemon() {
             //①获取fingerprintd
            mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(
            FINGERPRINTD));
            mDaemon.asBinder().linkToDeath(this, 0);
            //②向fingerprintd注册回调函数mDaemonCallback
            mDaemon.init(mDaemonCallback);
            //③调用获取fingerprintd的openhal函数
            mHalDeviceId = mDaemon.openHal();
            ......
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

app端通过Context获取FingerprintManager,通过调用FingerprintManager的接口来实现相应的功能,FingerprintManager转调FingerprintService中方法,FingerprintService负责管理整个注册,识别、删除指纹、检查权限等流程的逻辑,FingerprintService调用fingerprintd的接口,通过fingerprintd和FingerprintHal层进行通信。

三、fingerprintd

fingerprintd在system/core/fingerprintd目录下

这里写图片描述

fingerprintd可以分为四个部分: 
1. fingerprintd.cpp “负责将fingerprintd加入到ServiceManager中,以便FingerprintService能够获取” 
2. IFingerprintDaemon.h/IFingerprintDaemon.cpp “负责java层到fingerprintd的Binder通信(我们指纹录入和识别都会调用里面的方法)” 
3. FingerprintDaemonProxy.h/FingerprintDaemonProxy.cpp “负责fingerprintd和Fignerprint hal层的通信” 
4. IFingerprintDaemonCallback.h/IFingerprintDaemonCallback.cpp “负责将指纹的回调结果传给java层”

四、指纹录制流程

这里写图片描述

指纹录制的activity为FingerprintEnrollEnrolling实现了FingerprintEnrollSidecar.Listener 接口。

    //指纹录制时提示(比如太快,移动手指之类)
    @Override
    public void onEnrollmentHelp(CharSequence helpString) {
        mErrorText.setText(helpString);
    }
    //提示指纹录制过程中超时,或者未注册。
    @Override
    public void onEnrollmentError(int errMsgId, CharSequence errString) {
        int msgId;
         ......
         showErrorDialog(getText(msgId), errMsgId);
        ......
    }
    //录制过程中进度的变化
    @Override
    public void onEnrollmentProgressChange(int steps, int remaining) {
        updateProgress(true /* animate */);//更新进度
        updateDescription();//更新描述
        animateFlash();//更新动画
        ......
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

FingerprintEnrollSidecar的onStart方法中调用了startEnrollment(),该方法中调用FingeprintManager的enroll方法,并且传入了EnrollmentCallback对象,EnrollmentCallback是指纹录入结果的回调,分别调用了FingerprintEnrollSidecar.Listener 接口中的方法,这样就能更新指纹录制的进度和录制结果。

    private void startEnrollment() {
        ......
        mFingerprintManager.enroll(mToken, mEnrollmentCancel,
                0 /* flags */, mUserId, mEnrollmentCallback);
        mEnrolling = true;
    }

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

        @Override
        public void onEnrollmentProgress(int remaining) {
           ......
                mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
            }
        }

        @Override
        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
            if (mListener != null) {
                mListener.onEnrollmentHelp(helpString);
            }
        }

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

    public void enroll(byte [] token, CancellationSignal cancel, int flags,
            int userId, EnrollmentCallback callback) {
            ......
            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
                    mContext.getOpPackageName());
            ......

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

注意传入的mServiceReceiver对象,这个对象会通过handler发送相关消息去调用EnrollmentCallback或者AuthenticationCallback中方法。

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

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

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

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

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

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

public void handleMessage(android.os.Message msg) {
            switch(msg.what) {
                case MSG_ENROLL_RESULT:
                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                    break;
                case MSG_ACQUIRED:
                    sendAcquiredResult((Long) msg.obj /* deviceId */, 
                    msg.arg1 /* acquire info */);
                    break;
                case MSG_AUTHENTICATION_SUCCEEDED:
                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
                    break;
                case MSG_AUTHENTICATION_FAILED:
                    sendAuthenticatedFailed();
                    break;
                case MSG_ERROR:
                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
                    break;
                case MSG_REMOVED:
                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
                            msg.arg2 /* groupId */);
            }
        }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

FingerprintManager与FingerprintService直接通过aidl进行通信,在FingerprintService中内部类FingerprintServiceWrapper实现了IFingerprintService.Stub,我们调用的FingerManger的enroll方法就是调用FingerprintServiceWrapper类中的enroll()。

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

            final int enrolled = FingerprintService.this.
                    getEnrolledFingerprints(userId).size();
            if (enrolled >= limit) {
                Slog.w(TAG, "Too many fingerprints registered");
                return;
            }
            ......
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startEnrollment(token, cryptoToken, userId, receiver, 
                    flags,restricted, opPackageName);
                }
            });
        }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

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

    @Override
    public boolean onEnrollResult(int fingerId, int groupId, int remaining) {
        ......
        return sendEnrollResult(fingerId, groupId, remaining);
    }

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

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

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

start方法会调用fingerprintd,调用底层的指纹库,底层库返回结果后会调用onEnrollResult来反馈结果给receiver,在往上层反馈。这就是指纹的录制流程。

五、指纹的解锁流程

指纹解锁的核心类FingerprintUnlockController,实现了KeyguardUpdateMonitorCallback

public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
    @Override
    public void onFingerprintAuthenticated(int userId) {
        ......
        switch (mMode) {
            case MODE_DISMISS_BOUNCER://亮屏并且出现图案锁
                mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
                        false /* strongAuth */);
                break;
            case MODE_UNLOCK://亮屏不出现图案锁
                if (!wasDeviceInteractive) {
                    mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
                }
                mStatusBarKeyguardViewManager.animateCollapsePanels(
                        FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
                break;
            ......
            case MODE_WAKE_AND_UNLOCK://息屏锁屏解锁
                mStatusBarWindowManager.setStatusBarFocusable(false);
                mDozeScrimController.abortPulsing();
                mKeyguardViewMediator.onWakeAndUnlocking();
                mScrimController.setWakeAndUnlocking();
                if (mPhoneStatusBar.getNavigationBarView() != null) {
                    mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                }
                break;
            ......
            case MODE_DISMISS_KEYGUARD://通话界面息屏解锁
                mStatusBarWindowManager.setStatusBarFocusable(false);
                mKeyguardViewMediator.onWakeAndUnlocking();
                if (mPhoneStatusBar.getNavigationBarView() != null) {
                    mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                }
                break;
        }
        ......
    }

    @Override
    public void onFinishedGoingToSleep(int why) {
        ......
    }
    @Override
    public void onFingerprintAuthFailed() {
        cleanup();
    }

    @Override
    public void onFingerprintError(int msgId, String errString) {
        cleanup();

        if(Settings.Global.getInt(mContext.getContentResolver(),"persist.fg.errorshow",0) == 0){
            if(!mPowerManager.isScreenOn()){
                mPowerManager.wakeUp(SystemClock.uptimeMillis());
            }else {
                mStatusBarKeyguardViewManager.animateCollapsePanels(
                            FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
            }
            Settings.Global.putInt(mContext.getContentResolver(),"persist.fg.errorshow",1);
        }

    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

KeyguardUpdateMonitor类为解锁屏模块的监听者,它负责监听时间、sim卡、运营商信息、电池信息、电话信息等状态的变化,并通知keyguard View模块更新显示。这个类里面还有有监听指纹的方法startListeningForFingerprint, 该方法调用了FingerprintManager的authenticate()方法并且参数中传入了AuthenticationCallback对象,AuthenticationCallback类中调用了KeyguardUpdateMonitorCallback的方法,FingerprintUnlockController实现了KeyguardUpdateMonitorCallback这样就能实现指纹解锁。

private void startListeningForFingerprint() {
        ......
        //调用了FingerprintManager的authenticate()方法
        mFpm.authenticate(null, mFingerprintCancelSignal, 0, 
        mAuthenticationCallback, null, userId);
        ......
        }

 private FingerprintManager.AuthenticationCallback mAuthenticationCallback
            = new AuthenticationCallback() {
        //指纹匹配失败(没超过5次)
        @Override
        public void onAuthenticationFailed() {
            handleFingerprintAuthFailed();
        };
        //指纹匹配成功
        @Override
        public void onAuthenticationSucceeded(AuthenticationResult result) {
            handleFingerprintAuthenticated(result.getUserId());
        }
        //指纹匹配提示
        @Override
        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
            handleFingerprintHelp(helpMsgId, helpString.toString());
        }
        //指纹匹配错误(匹配失败次数超过5次)
        @Override
        public void onAuthenticationError(int errMsgId, CharSequence errString) {
            handleFingerprintError(errMsgId, errString.toString());
        }
        //获得到指纹
        @Override
        public void onAuthenticationAcquired(int acquireInfo) {
           if(Settings.Global.getInt(mContext.getContentResolver(),"persist.
            fg.errorshow",0) == 1){
                Settings.Global.putInt(mContext.getContentResolver(),"persist
                .fg.errorshow",0);
            }

            handleFingerprintAcquired(acquireInfo);
        }
    };

    private void handleFingerprintAuthenticated(int authUserId) {
        ......
        onFingerprintAuthenticated(userId);
        ......

    private void onFingerprintAuthenticated(int userId) {
        mUserFingerprintAuthenticated.put(userId, true);
        ......
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                //这里会调用FingerprintUnLockController中的onFingerprintAuthenticated方法处理解锁
                cb.onFingerprintAuthenticated(userId);
            }
        }
        .....
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

回来继续看FingerprintManager的authenticate()方法,此方法继续调用了FingerprintServiceWarpper的authenticate方法(FingerprintManager与FingerprintService直接通过aidl来通信)。

public void authenticate(@Nullable CryptoObject crypto, @Nullable 
        ......
        mService.authenticate(mToken, sessionId, userId, mServiceReceiver, 
                    flags,mContext.getOpPackageName());
        ......
    }
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
        @Override // Binder call
        public void authenticate(final IBinder token, final long opId, 
        final int groupId,final IFingerprintServiceReceiver receiver,
        final int flags,final String opPackageName) {
            startAuthentication(token, opId, callingUserId, groupId, 
            receiver, flags, restricted, opPackageName);
    }
    startAuthentication方法会调用AuthenticationClient的start方法,AuthenticationClient
    是为给定的客户端跟踪指纹认证状态。
    public abstract class AuthenticationClient extends ClientMonitor {

        public AuthenticationClient(Context context, long halDeviceId, IBinder token,
        IFingerprintServiceReceiver receiver, int targetUserId,
        int groupId, long opId,boolean restricted, String owner) {
            super(context, halDeviceId, token, receiver, targetUserId, 
            groupId, restricted, owner);
        }
        //指纹库处理结果调用
        @Override
        public boolean onAuthenticated(int fingerId, int groupId) {
            ......
            boolean authenticated = fingerId != 0;
            if (!authenticated) {
                //认证失败
                receiver.onAuthenticationFailed(getHalDeviceId());
            } else {
                //认证成功
                receiver.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId());
            }
            if (!authenticated) {
                if (inLockoutMode) {
                    //认证错误
                    receiver.onError(getHalDeviceId(),
                             FingerprintManager.FINGERPRINT_ERROR_LOCKOUT);
                  }
            }
            ......
        }
        /**
         * Start authentication
         */
        @Override
        public int start() {
            IFingerprintDaemon daemon = getFingerprintDaemon();
            ......
            final int result = daemon.authenticate(mOpId, getGroupId());
            ...... 
            return 0; // success
        }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

start方法会调用fingerprintd,调用底层的指纹库,底层库返回结果后会调用onAuthenticated来反馈结果给receiver,在往上层反馈。这就是指纹的识别流程。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值