從Android的官方API可以查到,向上層提供接口的是FingerprintManager,它的代碼在路徑frameworks/base/core/java/android/hardware/fingerprint下。
/**
* A class that coordinates access to the fingerprint hardware.
* @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting
* authentication. In a world where devices may have different types of biometric authentication,
* it's much more realistic to have a system-provided authentication dialog since the method may
* vary by vendor/device.
*/
@Deprecated
@SystemService(Context.FINGERPRINT_SERVICE)
@RequiresFeature(PackageManager.FEATURE_FINGERPRINT)
public class FingerprintManager implements BiometricFingerprintConstants
frameworks/base/core/java/android/hardware/fingerprint目錄下內容其實很少,一共只有幾個文件。
這裏除了FingerprintManager之外,就只有Fingerprint一個類了,其他都是aidl文件。
粗略的看了下Fingerprint類,它裏面的內容超級少,主要是包含了幾個成員變量,用來記錄指紋的信息。
/**
* Container for fingerprint metadata.
* @hide
*/
public final class Fingerprint extends BiometricAuthenticator.BiometricIdentifier {
private CharSequence mName;
private int mGroupId;
private int mFingerId;
private long mDeviceId; // physical device this is associated with
public Fingerprint(CharSequence name, int groupId, int fingerId, long deviceId) {
mName = name;
mGroupId = groupId;
mFingerId = fingerId;
mDeviceId = deviceId;
}
//...
}
如果仔細看代碼的話,可以發現一個很神奇的東西,那個就Fingerprint類的所有成員都是private的,並且沒有提供任何public的set方法!
這個就厲害了,因爲有做過指紋部分的朋友一定記得指紋提供一個rename的接口。沒有public的set方法,那它又是怎麼實現rename接口的呢?
帶着問題看源碼!
rename方法在Manager中的實現如下:
/**
* Renames the given fingerprint template
* @param fpId the fingerprint id
* @param userId the user who this fingerprint belongs to
* @param newName the new name
*
* @hide
*/
@RequiresPermission(MANAGE_FINGERPRINT)
public void rename(int fpId, int userId, String newName) {
// Renames the given fpId
if (mService != null) {
try {
mService.rename(fpId, userId, newName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
Slog.w(TAG, "rename(): Service not connected!");
}
}
這裏先直接找到Manager的服務類:FingerprintService
指紋服務的相關代碼在frameworks\base\services\core\java\com\android\server\fingerprint下。
/**
* A service to manage multiple clients that want to access the fingerprint HAL API.
* The service is responsible for maintaining a list of clients and dispatching all
* fingerprint-related events.
*
* @hide
*/
public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient
看一下它裏面的rename是在內部類FingerprintServiceWrapper中實現的,具體如下:
@Override // Binder call
public void rename(final int fingerId, final int groupId, final String name) {
checkPermission(MANAGE_FINGERPRINT);
if (!isCurrentUserOrProfile(groupId)) {
return;
}
mHandler.post(new Runnable() {
@Override
public void run() {
mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
groupId, name);
}
}
}
找到同文件夾下FingerprintUtils類,這個是工具類,裏面維護了一組FingerprintsUserState,具體得繼續看FingerprintsUserState;
FingerprintsUserState中維護了一組Fingerprint,下面具體看下rename操作:
@GuardedBy("this")
private final ArrayList<Fingerprint> mFingerprints = new ArrayList<Fingerprint>();
//...
public void renameFingerprint(int fingerId, CharSequence name) {
synchronized (this) {
for (int i = 0; i < mFingerprints.size(); i++) {
if (mFingerprints.get(i).getFingerId() == fingerId) {
Fingerprint old = mFingerprints.get(i);
mFingerprints.set(i, new Fingerprint(name, old.getGroupId(),
old.getFingerId(), old.getDeviceId()));
scheduleWriteStateLocked();
break;
}
}
}
}
這裏可以看到,在rename的實現時,代碼直接霸氣的new一個Fingerprint對象,然後覆蓋List中對應id的對象。
OK,以上只是一個小小的流程。
下面看下FingerprintManager的主要API:
public void enroll(byte [] token, CancellationSignal cancel, int flags,
int userId, EnrollmentCallback callback);
public void remove(Fingerprint fp, int userId, RemovalCallback callback);
public void rename(int fpId, int userId, String newName);
public List<Fingerprint> getEnrolledFingerprints();
//不是hide的方法
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler);
public boolean hasEnrolledFingerprints();
public boolean isHardwareDetected()
真正對三方開放的API只有最下面的三個,分別用來授權、判斷是否錄入過指紋、判斷設備是否支持指紋器件。
這裏面要特別提一下authenicate方法;
/**
* Request authentication of a crypto object. This call warms up the fingerprint hardware
* and starts scanning for a fingerprint. It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
* {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
* @param crypto object associated with the call or null if none required.
* @param cancel an object that can be used to cancel authentication
* @param flags optional flags; should be 0
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
*
* @throws IllegalArgumentException if the crypto operation is not supported or is not backed
* by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
* facility</a>.
* @throws IllegalStateException if the crypto primitive is not initialized.
* @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
* BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate(
* BiometricPrompt.CryptoObject, CancellationSignal, Executor,
* BiometricPrompt.AuthenticationCallback)}
*/
@Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
authenticate(crypto, cancel, flags, callback, handler, mContext.getUserId());
}
其中flags暫時沒用起來,直接設置爲0。
這裏稍微講下crypto objiect。它是的一個內部類。暫時支持三種類型對象。如下:
/**
* A wrapper class for the crypto objects supported by FingerprintManager. Currently the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
* @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}
*/
這個參數用於加密,保護指紋在使用過程中不被惡意軟件截獲和篡改。
Google的示例中用的是Cipher的加密對象。
需要結束監聽的話,使用CancellationSignal對象的cancel方法即可。
上面提到過Manager裏面的API具體實現都是Service中。
Manager中保存有Service的對象private IFingerprintService mService;
這對象看命名方式就可以大概猜到是個AIDL了;
/**
* Communication channel from client to the fingerprint service.
* @hide
*/
interface IFingerprintService
它是在Manager的構造函數作爲參數傳入的,找到創建Manager的地方:
frameworks/base/core/java/android/app/SystemServiceRegistry.java
registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class,
new CachedServiceFetcher<FingerprintManager>() {
@Override
public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
final IBinder binder;
if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE);
} else {
binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE);
}
IFingerprintService service = IFingerprintService.Stub.asInterface(binder);
return new FingerprintManager(ctx.getOuterContext(), service);
}});
從這裏看,關鍵字是Context.FINGERPRINT_SERVICE這個服務!
這時候,靈機一動看一眼FingerprintService(通過搜索可以搜到FingerprintService),它的onStart方法中有發佈這個服務,發佈的是它的內部類FingerprintServiceWrapper,這裏就解釋了爲什麼之前Manager裏面的rename方法最後會在FingerprintServiceWrapper被搜索到。
@Override
public void onStart() {
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
listenForUserSwitches();
}
而FingerprintService本身是在frameworks/base/services/java/com/android/server/SystemServer.java中啓動的;
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
traceBeginAndSlog("StartFingerprintSensor");
mSystemServiceManager.startService(FingerprintService.class);
traceEnd();
}
下面來看一下一個消息反饋的AIDL:IFingerprintServiceReceiver;
/**
* Communication channel from the FingerprintService back to FingerprintManager.
* @hide
*/
oneway interface IFingerprintServiceReceiver {
void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
void onAcquired(long deviceId, int acquiredInfo, int vendorCode);
void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId);
void onAuthenticationFailed(long deviceId);
void onError(long deviceId, int error, int vendorCode);
void onRemoved(long deviceId, int fingerId, int groupId, int remaining);
void onEnumerated(long deviceId, int fingerId, int groupId, int remaining);
}
它的實例在Manager中;
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub
作爲參數被傳遞給Service,實現消息反饋機制。
如果仔細看下FingerprintService所在的文件夾,除了之前提到過的FingerprintService、FingerprintUtils和FingerprintsUserState以外就只剩下大量和ClientMonitor 相關的類了;
/**
* Abstract base class for keeping track and dispatching events from fingerprint HAL to the
* the current client. Subclasses are responsible for coordinating the interaction with
* fingerprint HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
*/
public abstract class ClientMonitor implements IBinder.DeathRecipient
它的子類包括AuthenticationClient、EnrollClient、EnumerateClient、InternalEnumerateClient、InternalRemovalClient和RemovalClient。
它們是真正負責和更下層的HAL層交互的類。
HAL層有關的內容這裏暫不討論。
這樣的話,大概的一組流程被整理出來,FingerprintManager內部持有FingerprintService內部類FingerprintServiceWrapper的AIDL,FingerprintManager的API都是調用FingerprintServiceWrapper提供的接口實現的,同時通過參數實現IFingerprintServiceReceiver消息回傳。