您好,登錄后才能下訂單哦!
指紋服務(wù)是Android系統(tǒng)中一個(gè)較為簡(jiǎn)單的服務(wù)(相比于AMS,WMS等),也比較獨(dú)立,功能上包括幾點(diǎn)
和其他的system service 一樣,應(yīng)用程序通過(guò)FingerprintManager實(shí)現(xiàn)與FingerprintService的通信,除了上面所說(shuō)的功能之外,F(xiàn)ingerprintManager提供了一些別的的接口,重要的接口都會(huì)要求系統(tǒng)級(jí)別的權(quán)限,并且也不是公開的api(指紋的錄入,刪除,重命名,重置錯(cuò)誤計(jì)數(shù)等)
/** * 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的啟動(dòng)過(guò)程
FingerprintService在system server中創(chuàng)建并初始化,當(dāng)檢測(cè)到手機(jī)支持指紋功能的時(shí)候就會(huì)啟動(dòng)這個(gè)service
... if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mSystemServiceManager.startService(FingerprintService.class); } ...
FingerprintService在初始化后會(huì)建立和HAL層的通信,即連接到fingerprintd,拿到用于通信的IFingerprintDaemon對(duì)象(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; }
本質(zhì)上來(lái)說(shuō),除去安全相關(guān)的策略外,指紋的功能是依賴硬件實(shí)現(xiàn)的,F(xiàn)ingerprintService也只是充當(dāng)了framework java層與native層的消息傳遞者罷了,所以指紋的識(shí)別,錄入和監(jiān)聽都是向fingerprintd發(fā)送命令和獲取相應(yīng)的結(jié)果
指紋監(jiān)聽認(rèn)證過(guò)程
以指紋認(rèn)證為例,介紹這一過(guò)程,錄入和刪除的過(guò)程和認(rèn)證類似,不重復(fù)描述
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發(fā)送消息,但是開啟指紋認(rèn)證的函數(shù)傳入了兩個(gè)比較重要的參數(shù),一個(gè)是CancellationSignal對(duì)象,用于取消指紋認(rèn)證,另一個(gè)是指紋認(rèn)證的回調(diào)對(duì)象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) {} };
看函數(shù)名稱也能知道其功能,他們分別代表了指紋認(rèn)證時(shí)的回調(diào)結(jié)果(成功,失敗,檢測(cè)到指紋,認(rèn)證異常等),參數(shù)包含了具體的信息,這些信息在FingerprintManager中都有對(duì)應(yīng)的常量定義,有興趣可以查看代碼
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); } }); }
前面會(huì)有對(duì)包名,userid以及應(yīng)用進(jìn)程是否在在前臺(tái)的檢查,繼續(xù)看
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,用于處理指紋認(rèn)證相關(guān)的功能事務(wù),ClientMonitor的其他子類如RemovalMonior,EnrollMonitor也是如此,ClientMonitor會(huì)直接與fingerprintd通信,其核心是調(diào)用其start()或stop()方法,
對(duì)于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 }
向底層發(fā)送認(rèn)證命令后就只需要等待認(rèn)證結(jié)果就可以了,前面我們說(shuō)到在初始化的時(shí)候會(huì)建立與fingerprintd的通信,其核心是下面這行代碼
mDaemon.init(mDaemonCallback);
mDaemonCallback是一個(gè)binder對(duì)象,接受來(lái)自底層的結(jié)果,然后通過(guò)FingerprintService和FingerManager一層層把結(jié)果發(fā)送到應(yīng)用程序中去。
8.0的一些變化
8.0上的fingerprintd變化很大,甚至都不叫fingerprintd了,當(dāng)然這是native層的東西,這里不討論,對(duì)于FingerprintService而言,一個(gè)顯著的變化是安全策略的調(diào)整
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; }
總結(jié)
以上所述是小編給大家介紹的Android7.0指紋服務(wù)FingerprintService實(shí)例介紹,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。