POST
Android Fingerprint Framework (2)
This page will follow the last article to continue introducing the android fingerprint framework knowledge. The content is focused on android source code inspecting and analysis.
Step one - startup fingerprintd service
Looking at the init.rc
file, a task is assigned at init.rc
when the android system boots up - start the fingerprint daemon service.
service fingerprintd /system/bin/fingerprintd
class late_start
user root
group root sdcard_r sdcard_rw
Let’s go on to check the fingerprintd
program.
Here I would recommend a useful website for you viewing the android source code.
Android Community
We can see the android path of the fingerprintd.cpp is system/core/fingerprintd/
and the directory structure is as below.
read the
Android.mk
androdi path: root/system/core/fingerprintd/Android.mk
we can know that this package is built as a executable program.
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)
next open the
fingerprintd.cpp
android path: root/system/core/fingerprintd/fingerprintd.cpp
The task of the main()
function is very simple, just create a FingerprintDaemonProxy
object and add it into the service queue.
#include "FingerprintDaemonProxy.h"
int main() {
ALOGI("Starting " LOG_TAG);
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;
}
/*
* We're the only thread in existence, so we're just going to process
* Binder transaction as a single-threaded program.
*/
android::IPCThreadState::self()->joinThreadPool();
ALOGI("Done");
return 0;
}
From the
FingerprintDaemonProxy.h
android path: root/system/core/fingerprintd/
FingerprintDaemonProxy.h
We find the remote service is fingerprint daemon. Fingerprinted
registers the remote service to the servicemanager for the client to use.
The protocol interface is IFingerprintdaemon
. FingerprintService
in the framework will eventually call the remote service, that is, the method in
fingerprintdaemonproxy.cpp.
android path: root/system/core/fingerprintd/
fingerprintdaemonproxy.cpp
++
#ifndef FINGERPRINT_DAEMON_PROXY_H_
#define FINGERPRINT_DAEMON_PROXY_H_
#include "IFingerprintDaemon.h"
#include "IFingerprintDaemonCallback.h"
namespace android {
class FingerprintDaemonProxy : public BnFingerprintDaemon {
public:
static FingerprintDaemonProxy* getInstance() {
if (sInstance == NULL) {
sInstance = new FingerprintDaemonProxy();
}
return sInstance;
}
// These reflect binder methods.
virtual void init(const sp<IFingerprintDaemonCallback>& callback);
virtual int32_t enroll(const uint8_t* token, ssize_t
tokenLength, int32_t groupId, int32_t timeout);
virtual uint64_t preEnroll();
virtual int32_t postEnroll();
virtual int32_t stopEnrollment();
virtual int32_t authenticate(uint64_t sessionId, uint32_t
groupId);
virtual int32_t stopAuthentication();
virtual int32_t remove(int32_t fingerId, int32_t groupId);
virtual int32_t enumerate();
virtual uint64_t getAuthenticatorId();
virtual int32_t setActiveGroup(int32_t groupId,
const uint8_t* path, ssize_t pathLen);
virtual int64_t openHal();
virtual int32_t closeHal();
private:
FingerprintDaemonProxy();
virtual ~FingerprintDaemonProxy();
void binderDied(const wp<IBinder>& who);
void notifyKeystore(const uint8_t *auth_token, const size_t
auth_token_length);
static void hal_notify_callback(const fingerprint_msg_t *msg);
static FingerprintDaemonProxy* sInstance;
fingerprint_module_t const* mModule;
fingerprint_device_t* mDevice;
sp<IFingerprintDaemonCallback> mCallback;
};
} // namespace android
#endif // FINGERPRINT_DAEMON_PROXY_H_
Step two - Startup FingerprintService
Next, we will move to the framework layer to find how the Fingerprint Service starts up.
open the
SystemServer.java
android path: root/frameworks/base/services/java/com/android/server/
SystemServer.java
This class is in charge of system service management, include start-up the necessary service.
When the Android system loads the system server, starts Fingerprint Service.
import com.android.server.fingerprint.FingerprintService;
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
traceBeginAndSlog("StartFingerprintSensor");
mSystemServiceManager.startService(FingerprintService.class);
traceEnd();
}
Keep looking into the
FingerprintService.java.
android path: root/frameworks/base/services/core/java/com/android/server/fingerprint/FingerprintService.java
FingerprintService
is a subclass of SystemService
class and implements the IHwbinder
interface.
public class FingerprintService extends SystemService implements
IHwBinder.DeathRecipient {
public synchronized IBiometricsFingerprint getFingerprintDaemon() {
if (mDaemon == null) {
Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
try {
mDaemon = IBiometricsFingerprint.getService();
} catch (java.util.NoSuchElementException e) {
// Service doesn't exist or cannot be opened. Logged below.
} catch (RemoteException e) {
Slog.e(TAG, "Failed to get biometric interface", e);
}
if (mDaemon == null) {
Slog.w(TAG, "fingerprint HIDL not available");
return null;
}
mDaemon.asBinder().linkToDeath(this, 0);
try {
mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to open fingerprint HAL", e);
mDaemon = null; // try again later!
}
if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
if (mHalDeviceId != 0) {
loadAuthenticatorIds();
updateActiveGroup(ActivityManager.getCurrentUser(), null);
doFingerprintCleanupForUser(ActivityManager.getCurrentUser());
} else {
Slog.w(TAG, "Failed to open Fingerprint HAL!");
MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
mDaemon = null;
}
}
return mDaemon;
}
}
Let’s see the method getFingerprintDaemon()
, this method will acquire the fingerprint remote service object, that is, the object of fingerprint daemon (system/core/fingerprintd)
, which has been registered in the init.rc. Then initialize the remote service fingerprintdaemon
and set the callback mDaemonCallback
.
It can be seen from the above that the fingerprint service in the framework calls the fingerprint remote service of the native layer fingerprint daemon (related to the hardware), which can be regarded as the client of the fingerprint remote service fingerprint daemon.
Ok, we have already gone through the working process of the framework layer and how they register the system service and access the HAL code by calling the remote Fingerprint Service through Binder. Let’s move to the native layer in the next article.