国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android7.0指紋服務FingerprintService實例介紹

2019-10-22 18:17:29
字體:
來源:轉載
供稿:網友

指紋服務是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,       flags, restricted, opPackageName);    }   });  }

前面會有對包名,userid以及應用進程是否在在前臺的檢查,繼續看

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 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實例介紹,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 靖江市| 边坝县| 镇远县| 资阳市| 彭州市| 松桃| 玉门市| 乡宁县| 蒲江县| 石河子市| 汾阳市| 肇庆市| 信阳市| 镇远县| 佛学| 五原县| 承德县| 雅安市| 东安县| 通江县| 广平县| 奉贤区| 青河县| 株洲市| 原平市| 宁南县| 芜湖县| 哈尔滨市| 开鲁县| 华安县| 钟祥市| 富锦市| 甘南县| 老河口市| 滕州市| 樟树市| 东平县| SHOW| 浑源县| 开江县| 浪卡子县|