前言
爲了更好地閱讀本文,你需要先閱讀 Android Fingerprint完全解析(一) :Fingerprint整體框架 這篇文章,在此文中,博主分析了Android 6.0 版本TEE 環境下 Fingerprint 的總體框架。閱讀本文前,您需要對Android Binder 有一些瞭解。
步驟一.啓動Fingerprintd
在init.rc 文件中啓動fingerprintd ;這個fingerprintd 是一個可執行文件。
service fingerprintd /system/bin/fingerprintd
class late_start
user root
group root sdcard_r sdcard_rw
fingerprintd (system/core/fingerprintd 目錄)
fingerprintd 的Android.mk 文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
LOCAL_SRC_FILES := \
FingerprintDaemonProxy.cpp \
IFingerprintDaemon.cpp \
IFingerprintDaemonCallback.cpp \
fingerprintd.cpp
LOCAL_MODULE := fingerprintd
LOCAL_SHARED_LIBRARIES := \
libbinder \
liblog \
libhardware \
libutils \
libkeystore_binder
include $(BUILD_EXECUTABLE)
從mk文件中 BUILD_EXECUTABLE 得知,此進程是一個可執行文件。
int main() {
android::sp<android::IServiceManager> serviceManager = android::defaultServiceManager();
android::sp<android::FingerprintDaemonProxy> proxy =
android::FingerprintDaemonProxy::getInstance();
android::status_t ret = serviceManager->addService(
android::FingerprintDaemonProxy::descriptor, proxy);
if (ret != android::OK) {
ALOGE("Couldn't register " LOG_TAG " binder service!");
return -1;
}
android::IPCThreadState::self()->joinThreadPool();
return 0;
}
啓動 native 層的指紋系統服務,調用addService()方法,向serivcemanager 註冊server。
這裏用到Binder的IPC通信方式,這裏可以自行去研究下;
從FingerprintDaemonProxy.h 這個文件可以看出,根據android Binder的知識,可以知道這個遠程服務是FingerprintDaemon。 Fingerprintd 把這個遠程服務,註冊到serivcemanager,供客戶調用,這個遠程服務
協議接口是 IFingerprintDaemon,framework 中的FingerprintSerVice 最終會調用這個遠程服務,也就是會調用FingerprintDaemonProxy.cpp 裏面的方法。
步驟二.啓動FingerprintService
SystemServer.java
mSystemServiceManager.startService(FingerprintService.class);
Android系統在加載SystemServer時候,去啓動FingerprintService 指紋系統服務 (frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java),
調用FingerprintService 的onStart() 方法,如下:
步驟三.訪問指紋遠程服務(native層的)
進入到1194 行 IFingerprintDaemon daemon = getFingerprintDaemon(),IFingerprintDaemon 從名字可以猜測這個是提供訪問遠程服務的協議接口。
private static final String FINGERPRINTD = "android.hardware.fingerprint.IFingerprintDaemon";
getFingerprintDaemon() 函數有如下動作:
-
171行 獲取指紋遠程Service對象,即FingerprintDaemon的對象(System/core/fingerprintd)
mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
-
175行 初始化遠程服務FingerprintDaemon,並且設置回調DaemonCallback
- 176行 調用遠程服務FingerprintDaemon 的openHal() 方法。
總結:
由上可知,framework中的FingerprintService 調用native層的指紋遠程服務FingerprintDaemon(跟硬件有關係),可以把FingerprintService 看做指紋遠程服務FingerprintDaemon的客戶端。
步驟四.打開Fingerprint Hal層
步驟三中,
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());
} else {
Slog.w(TAG, "Failed to open Fingerprint HAL!");
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;
}
getFingerprintDaemon() 方法會調用 mDaemon.init(mDaemonCallback), mDaemon.openHal() ,兩個方法,其實就是調用FingerprintDaemonProxy.cpp 的init()函數 跟openHal() 函數。
openHal() 函數中會去打開指紋 HAl層 即,fingerprint.xx.so。
總結,整個流程如下:
1.init.rc,啓動fingerprintd,並向serivcemanager註冊遠程服務 FingerprintDaemon
2.系統加載SystemServer ,啓動FingerprintService。
3.FingerprintService獲取遠程服務FingerprintDaemon的對象,調用相關函數
4.FingerprintService調用openHal函數,打開指紋Hal 層