Android N指纹识别

来源:互联网 发布:Linux修改进程名字 编辑:程序博客网 时间:2024/06/08 04:55

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

一、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.DreamManagerService05-29 10:37:57.874643  1127  1127 I SystemServer: StartAssetAtlasService05-29 10:37:57.883240  1127  1127 I SystemServiceManager: Starting com.android.server.print.PrintManagerService05-29 10:37:57.910104  1127  1127 I SystemServiceManager: Starting com.android.server.restrictions.RestrictionsManagerService05-29 10:37:57.913926  1127  1127 I SystemServiceManager: Starting com.android.server.media.MediaSessionService05-29 10:37:57.926584  1127  1127 I SystemServer: StartMediaRouterService05-29 10:37:57.939619  1127  1127 I SystemServiceManager: Starting com.android.server.trust.TrustManagerService05-29 10:37:57.952689  1127  1127 I SystemServiceManager: Starting com.android.server.fingerprint.FingerprintService05-29 10:37:58.866228  1127  1127 V FingerprintService: Fingerprint HAL id: 48834523596805-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,在往上层反馈。这就是指纹的识别流程。