Android Fingerprint Framework (1): FingerprintManager

蔣承達 (Jazz)
6 min readJan 2, 2019

--

前一陣子因為完成了一個客戶需求客製化的 Fingerprint 功能,將 Android 原生的 Fingerprint 設計上下翻了一次,那索性就來介紹一下 Fingerprint 的架構吧。

預計會分成 FingerprintManager、FingerprintService、Fingerprint HAL、Fingerprint under Android P 這四個部分來介紹。而我們今天先來介紹 FingerprintManager。

FingerprintManager 主要的位置: /frameworks/base/core/java/android/hardware/ \
fingerprint/FingerprintManager.java

我們可以看到主要有關 Fingerprint 的 function 都在這隻檔案裡面,其中我們最關心的幾個主要的 function 就是 Enroll(註冊指紋)、Authenticate(驗證指紋)、Remove(移除指紋)、Enumerate(列舉指紋)。

接下來我們以 Enroll 為範例來追一下整個 code flow、其實相當的簡單

首先我們可以看到有幾個值得介紹的地方:

1. MANAGE_FINGERPRINT 權限:

注記此功能需要 MANAGE_FINGERPRINT 這個權限,而這個權限並非所有的 APP 都可以獲得。只有 Platform APP 可以得到管理指紋的權限,例如說手機中的 Settings,這樣使用者才能用 Settings 來註冊指紋解鎖。

2. 引數中的 EnrollmentCallback 類別:

EnrollmentCallback 是定義在 FingerprintManager 裡面的抽象類別,目的是讓呼叫者先實作每個狀況發生時該做甚麼,再帶入 Enroll function 中使用。

EnrollmentCallback 可以處理的事件有:
- onEnrollmentError (註冊程序失敗而中止)
- onEnrollmentHelp (註冊有問題並給予提示重做)
- onEnrollmentProgress (註冊順利進行並回應還剩下幾次觸碰完成註冊)

其實每一個 FingerprintManager 的重要 function 幾乎都有定義自己的 callback 抽象類別來取得回應資訊,如同 Enroll 在使用前都要先實作。

3. 引數中的 CancellationSignal 類別:

來自 framework 系統內的一個類別
frameworks/base/core/java/android/os/CancellationSignal.java

使用者會 new 了一個 CancellationSignal 的實體之後帶進 function 中,在 enroll function 中會自己設定好 onCancel 時要做的事,使用者不需要費心。
在這裡設定的是 OnEnrollCancelListener:

接著在 CancellationSignal 裡面會把接到的 OnCancelListener 設定成類別成員變數 mOnCancelListener,並且先執行一次 onCancel():

設定好了之後使用者如果希望取消註冊程序,只需要呼叫他自己 new 的 CancellationSignal 實體裡面的 cancel():

就可以一路呼叫到定義在 FingerprintManager 裡面的 cancelEnrollment()

這裡的設計是一個有趣的範例,讓使用者並非透過直接呼叫 FingerprintManager 裡的某個 cancel 功能,而是握有一個物件,需要的時候,例如說按下按鈕時,只要執行此物件裡的 cancel 就可以了。

4. mService 物件:

enroll 最後呼叫了 mService.enroll(mToken, token, …);
而 mService 又是哪裡來的呢?
我們可以看到 mService 是一個 IFingerprintService 的 interface:

是在 FingerprintManager 創建時就一起帶進來的:

而 FingerprintManager 的實體又在哪裡被創建呢? 請看
frameworks/base/core/java/android/app/SystemServiceRegistry.java

在 SystemServiceRegistry 中看到了我們將 FINGERPRINT_SERVICE 這個 Service 取出並使用 IFingerprintService 來包裝,再帶入 FingerprintManager 的建構子裡。
所以 mService 就是 IFingerprintService 就是 FINGERPRINT_SERVICE。

那 FINGERPRINT_SERVICE 又是甚麼呢?

請看
frameworks/base/services/core/java/com/android/server/fingerprint/ \
FingerprintService.java:

原來在 FingerprintService 啟動的時候就會把 FingerprintServiceWrapper 公開註冊成 FINGERPRINT_SERVICE。

而如下,FingerprintServiceWrapper 本身就是定義實作 IFingerprintService 內容的地方,難怪可以被包裝成 IFingerprintService 的物件,而裡面就定義了下一步要使用的 enroll(final IBinder token, …)

因此就實現了這個簡單的 code flow:
FingerprintManager: enroll()

FingerprintManager: mService.enroll()

FingerprintService: FingerprintServiceWrapper: enroll()

FingerprintService: startEnrollment()

一路 call 進FingerprintService 裡面去了。

因為篇幅的關係 FingerprintService 的架構將放到下一篇再講,希望大家都有收穫。

--

--

蔣承達 (Jazz)
蔣承達 (Jazz)

Written by 蔣承達 (Jazz)

Thundercomm - Software Development Manager

No responses yet