Android7.0指纹服务FingerprintService实例介绍

Android7.0指纹服务FingerprintService实例介绍,第1张

概述指纹服务是Android系统中一个较为简单的服务(相比于AMS,WMS等),也比较独立,功能上包括几点

指纹服务是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实例介绍所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143136.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存