指纹服务是AndroID系统中一个较为简单的服务(相比于AMS,WMS等),也比较独立,功能上包括几点
指纹的录入与删除 指纹认证 指纹的安全策略(错误次数判定)和其他的system service 一样,应用程序通过FingerprintManager实现与FingerprintService的通信,除了上面所说的功能之外,FingerprintManager提供了一些别的的接口,重要的接口都会要求系统级别的权限,并且也不是公开的API(指纹的录入,删除,重命名,重置错误计数等)
/** * Obtain the List of enrolled fingerprints templates. * @return List of current fingerprint items * * @hIDe */ @RequiresPermission(USE_FINGERPRINT) public List<Fingerprint> getEnrolledFingerprints(int userID) { if (mService != null) try { return mService.getEnrolledFingerprints(userID,mContext.getopPackagename()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } return null; } /** * @hIDe */ @RequiresPermission(allOf = { USE_FINGERPRINT,INteraCT_ACROSS_USERS}) public boolean hasEnrolledFingerprints(int userID) { if (mService != null) try { return mService.hasEnrolledFingerprints(userID,mContext.getopPackagename()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } return false; } /** * Determine if fingerprint harDWare is present and functional. * * @return true if harDWare is present and functional,false otherwise. */ @RequiresPermission(USE_FINGERPRINT) public boolean isHarDWareDetected() { if (mService != null) { try { long deviceid = 0; /* Todo: plumb harDWare ID to FPMS */ return mService.isHarDWareDetected(deviceid,mContext.getopPackagename()); } catch (remoteexception e) { throw e.rethrowFromSystemServer(); } } else { Log.w(TAG,"isFingerprintHarDWareDetected(): Service not connected!"); } return false; }
FingerprintService的启动过程
FingerprintService在system server中创建并初始化,当检测到手机支持指纹功能的时候就会启动这个service
...if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mSystemServiceManager.startService(FingerprintService.class); }...
FingerprintService在初始化后会建立和HAL层的通信,即连接到fingerprintd,拿到用于通信的IFingerprintDaemon对象(binder)
public voID onStart() { publishBinderService(Context.FINGERPRINT_SERVICE,new FingerprintServiceWrapper()); IFingerprintDaemon daemon = getFingerprintDaemon(); ListenForUserSwitches(); }public IFingerprintDaemon getFingerprintDaemon() { if (mDaemon == null) { mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD)); if (mDaemon != null) { try { mDaemon.asBinder().linkToDeath(this,0); mDaemon.init(mDaemonCallback); mHaldeviceid = mDaemon.openHal(); if (mHaldeviceid != 0) { updateActiveGroup(ActivityManager.getCurrentUser(),null); } else { Slog.w(TAG,"Failed to open Fingerprint HAL!"); Metricslogger.count(mContext,"fingerprintd_openhal_error",1); mDaemon = null; } } catch (remoteexception e) { Slog.e(TAG,"Failed to open fingeprintd HAL",e); mDaemon = null; // try again later! } } else { Slog.w(TAG,"fingerprint service not available"); } } return mDaemon; }
本质上来说,除去安全相关的策略外,指纹的功能是依赖硬件实现的,FingerprintService也只是充当了framework java层与native层的消息传递者罢了,所以指纹的识别,录入和监听都是向fingerprintd发送命令和获取相应的结果
指纹监听认证过程
以指纹认证为例,介绍这一过程,录入和删除的过程和认证类似,不重复描述
FingerprintManager
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)); } } }
可以看到,最终仍然是向FingerprintService发送消息,但是开启指纹认证的函数传入了两个比较重要的参数,一个是CancellationSignal对象,用于取消指纹认证,另一个是指纹认证的回调对象AuthenticationCallback
public static abstract class AuthenticationCallback { public voID onAuthenticationError(int errorCode,CharSequence errString) { } public voID onAuthenticationHelp(int helpCode,CharSequence helpString) { } public voID onAuthenticationSucceeded(AuthenticationResult result) { } public voID onAuthenticationFailed() { } public voID onAuthenticationAcquired(int acquireInfo) {} };
看函数名称也能知道其功能,他们分别代表了指纹认证时的回调结果(成功,失败,检测到指纹,认证异常等),参数包含了具体的信息,这些信息在FingerprintManager中都有对应的常量定义,有兴趣可以查看代码
FingerprintService
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 callingUserID = UserHandle.getCallingUserID(); final int pID = Binder.getCallingPID(); final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @OverrIDe public voID run() { if (!canUseFingerprint(opPackagename,true /* foregroundOnly */,callingUID,pID)) { if (DEBUG) Slog.v(TAG,"authenticate(): reject " + opPackagename); return; } 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,restricted,opPackagename); } }); }
前面会有对包名,userID以及应用进程是否在在前台的检查,继续看
private voID startAuthentication(IBinder token,long opID,int callingUserID,int groupID,IFingerprintServiceReceiver receiver,boolean restricted,String opPackagename) { updateActiveGroup(groupID,opPackagename); if (DEBUG) Slog.v(TAG,"startAuthentication(" + opPackagename + ")"); AuthenticationClIEnt clIEnt = new AuthenticationClIEnt(getContext(),mHaldeviceid,token,mCurrentUserID,opPackagename) { @OverrIDe public boolean handleFailedAttempt() { mFailedAttempts++; if (mFailedAttempts == MAX_Failed_ATTEMPTS) { mPerformanceStats.lockout++; } if (inLockoutMode()) { // Failing multiple times will continue to push out the lockout time. scheduleLockoutreset(); return true; } return false; } @OverrIDe public voID resetFailedAttempts() { FingerprintService.this.resetFailedAttempts(); } @OverrIDe public voID notifyUserActivity() { FingerprintService.this.userActivity(); } @OverrIDe public IFingerprintDaemon getFingerprintDaemon() { return FingerprintService.this.getFingerprintDaemon(); } }; if (inLockoutMode()) { Slog.v(TAG,"In lockout mode; disallowing authentication"); // Don't bother starting the clIEnt. Just send the error message. if (!clIEnt.onError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { Slog.w(TAG,"Cannot send timeout message to clIEnt"); } return; } startClIEnt(clIEnt,true /* initiatedByClIEnt */); }
AuthenticationClIEnt继承自ClIEntMonitor,用于处理指纹认证相关的功能事务,ClIEntMonitor的其他子类如RemovalMonior,EnrollMonitor也是如此,ClIEntMonitor会直接与fingerprintd通信,其核心是调用其start()或stop()方法,
对于AuthenticationClIEnt而言
private voID startClIEnt(ClIEntMonitor newClIEnt,boolean initiatedByClIEnt) { ClIEntMonitor currentClIEnt = mCurrentClIEnt; if (currentClIEnt != null) { if (DEBUG) Slog.v(TAG,"request stop current clIEnt " + currentClIEnt.getownerString()); 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 + ")"); newClIEnt.start(); } }public int start() { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG,"start authentication: no fingeprintd!"); return ERROR_ESRCH; } try { final int result = daemon.authenticate(mOpID,getGroupID()); if (result != 0) { Slog.w(TAG,"startAuthentication Failed,result=" + result); Metricslogger.histogram(getContext(),"fingeprintd_auth_start_error",result); onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); return result; } if (DEBUG) Slog.w(TAG,"clIEnt " + getownerString() + " is authenticating..."); } catch (remoteexception e) { Slog.e(TAG,"startAuthentication Failed",e); return ERROR_ESRCH; } return 0; // success }
向底层发送认证命令后就只需要等待认证结果就可以了,前面我们说到在初始化的时候会建立与fingerprintd的通信,其核心是下面这行代码
mDaemon.init(mDaemonCallback);
mDaemonCallback是一个binder对象,接受来自底层的结果,然后通过FingerprintService和FingerManager一层层把结果发送到应用程序中去。
8.0的一些变化
8.0上的fingerprintd变化很大,甚至都不叫fingerprintd了,当然这是native层的东西,这里不讨论,对于FingerprintService而言,一个显著的变化是安全策略的调整
8.0之前,指纹只能错误5次,达到5次时会禁止指纹认证,同时开启30秒倒计时,等待结束后重置错误计数,继续认证 8.0之后,依然是每错误5次就会倒计时30秒,然而30秒结束后错误计数并不会被清空,8.0上加入了最大20次的限制,累计错误20次之后就无法使用指纹认证功能了,只能用密码的方式才能重置错误计数private static final int MAX_Failed_ATTEMPTS_LOCKOUT_TIMED = 5;private static final int MAX_Failed_ATTEMPTS_LOCKOUT_PERMANENT = 20;private int getLockoutMode() { if (mFailedAttempts >= MAX_Failed_ATTEMPTS_LOCKOUT_PERMANENT) { return AuthenticationClIEnt.LOCKOUT_PERMANENT; } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false && (mFailedAttempts % MAX_Failed_ATTEMPTS_LOCKOUT_TIMED == 0)) { return AuthenticationClIEnt.LOCKOUT_TIMED; } return AuthenticationClIEnt.LOCKOUT_NONE; }
总结
以上所述是小编给大家介绍的Android7.0指纹服务FingerprintService实例介绍,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android7.0指纹服务FingerprintService实例介绍全部内容,希望文章能够帮你解决Android7.0指纹服务FingerprintService实例介绍所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)