亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2020-09-20 14:12:29 來源:腳本之家 閱讀:225 作者:qh_94d8 欄目:移動開發

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

深圳市| 江都市| 长治市| 灯塔市| 黑河市| 蓝田县| 湖北省| 万全县| 云浮市| 盐山县| 新蔡县| 韩城市| 和平区| 怀化市| 怀集县| 庆阳市| 富川| 阜城县| 临汾市| 西乌珠穆沁旗| 孟村| 东乡| 苗栗市| 宁强县| 福泉市| 平武县| 沾化县| 嘉善县| 白山市| 景宁| 上蔡县| 博野县| 股票| 南宁市| 太原市| 庆城县| 永春县| 新平| 桦南县| 东兴市| 榆社县|