mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
clean up default fingerprint HIDL@2.1 implementation
- remove Binder dependency by passing keystore token to onAuthenticated() - move notify() to cpp file Test: recovers from killing keystore, fingerprint unlocks device, FingerprintDialog works with crypto objects. Fixes bug 34264028 Change-Id: Ic0de31603f4bc4147d6faf014af89e787b1ef244
This commit is contained in:
@@ -43,8 +43,9 @@ interface IBiometricsFingerprintClientCallback {
|
||||
* @param deviceId the instance of this fingerprint device
|
||||
* @param fingerId the fingerprint templetate that was authenticated
|
||||
* @param groupId the groupid for the template that was authenticated
|
||||
* @param token the hardware authentication token to pass to Keystore.addAuthToken()
|
||||
*/
|
||||
oneway onAuthenticated(uint64_t deviceId, uint32_t fingerId, uint32_t groupId);
|
||||
oneway onAuthenticated(uint64_t deviceId, uint32_t fingerId, uint32_t groupId, vec<uint8_t> token);
|
||||
|
||||
/**
|
||||
* Sent when a fingerprint error occurs
|
||||
|
||||
@@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#define LOG_TAG "android.hardware.biometrics.fingerprint@2.1-service"
|
||||
#define LOG_VERBOSE "android.hardware.biometrics.fingerprint@2.1-service"
|
||||
|
||||
// For communication with Keystore binder interface
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <keystore/IKeystoreService.h>
|
||||
#include <keystore/keystore.h> // for error codes
|
||||
#include <hardware/hw_auth_token.h>
|
||||
|
||||
@@ -40,23 +39,19 @@ static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1);
|
||||
using RequestStatus =
|
||||
android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
|
||||
|
||||
sp<IBiometricsFingerprintClientCallback>
|
||||
BiometricsFingerprint::mClientCallback = nullptr;
|
||||
BiometricsFingerprint *BiometricsFingerprint::sInstance = nullptr;
|
||||
|
||||
// TODO: This is here because HAL 2.1 doesn't have a way to propagate a
|
||||
// unique token for its driver. Subsequent versions should send a unique
|
||||
// token for each call to notify(). This is fine as long as there's only
|
||||
// one fingerprint device on the platform.
|
||||
fingerprint_device_t *BiometricsFingerprint::sDevice = nullptr;
|
||||
|
||||
BiometricsFingerprint::BiometricsFingerprint(fingerprint_device_t *device)
|
||||
: mDevice(device) {
|
||||
sDevice = mDevice; // keep track of the most recent instance
|
||||
BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr), mDevice(nullptr) {
|
||||
sInstance = this; // keep track of the most recent instance
|
||||
mDevice = openHal();
|
||||
if (!mDevice) {
|
||||
ALOGE("Can't open HAL module");
|
||||
}
|
||||
}
|
||||
|
||||
BiometricsFingerprint::~BiometricsFingerprint() {
|
||||
ALOG(LOG_VERBOSE, LOG_TAG, "nativeCloseHal()\n");
|
||||
if (mDevice == NULL) {
|
||||
ALOGV(LOG_VERBOSE, LOG_TAG, "~BiometricsFingerprint()\n");
|
||||
if (mDevice == nullptr) {
|
||||
ALOGE("No valid device");
|
||||
return;
|
||||
}
|
||||
@@ -66,7 +61,7 @@ BiometricsFingerprint::~BiometricsFingerprint() {
|
||||
ALOGE("Can't close fingerprint module, error: %d", err);
|
||||
return;
|
||||
}
|
||||
mDevice = NULL;
|
||||
mDevice = nullptr;
|
||||
}
|
||||
|
||||
Return<RequestStatus> BiometricsFingerprint::ErrorFilter(int32_t error) {
|
||||
@@ -107,6 +102,8 @@ FingerprintError BiometricsFingerprint::VendorErrorFilter(int32_t error,
|
||||
return FingerprintError::ERROR_CANCELED;
|
||||
case FINGERPRINT_ERROR_UNABLE_TO_REMOVE:
|
||||
return FingerprintError::ERROR_UNABLE_TO_REMOVE;
|
||||
case FINGERPRINT_ERROR_LOCKOUT:
|
||||
return FingerprintError::ERROR_LOCKOUT;
|
||||
default:
|
||||
if (error >= FINGERPRINT_ERROR_VENDOR_BASE) {
|
||||
// vendor specific code.
|
||||
@@ -114,7 +111,7 @@ FingerprintError BiometricsFingerprint::VendorErrorFilter(int32_t error,
|
||||
return FingerprintError::ERROR_VENDOR;
|
||||
}
|
||||
}
|
||||
ALOGE("Unknown error from fingerprint vendor library");
|
||||
ALOGE("Unknown error from fingerprint vendor library: %d", error);
|
||||
return FingerprintError::ERROR_UNABLE_TO_PROCESS;
|
||||
}
|
||||
|
||||
@@ -143,13 +140,17 @@ FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(
|
||||
return FingerprintAcquiredInfo::ACQUIRED_VENDOR;
|
||||
}
|
||||
}
|
||||
ALOGE("Unknown acquiredmsg from fingerprint vendor library");
|
||||
ALOGE("Unknown acquiredmsg from fingerprint vendor library: %d", info);
|
||||
return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
|
||||
}
|
||||
|
||||
Return<uint64_t> BiometricsFingerprint::setNotify(
|
||||
const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
|
||||
mClientCallback = clientCallback;
|
||||
// This is here because HAL 2.1 doesn't have a way to propagate a
|
||||
// unique token for its driver. Subsequent versions should send a unique
|
||||
// token for each call to setNotify(). This is fine as long as there's only
|
||||
// one fingerprint device on the platform.
|
||||
return reinterpret_cast<uint64_t>(mDevice);
|
||||
}
|
||||
|
||||
@@ -199,36 +200,44 @@ Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId,
|
||||
}
|
||||
|
||||
IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
|
||||
if (!sInstance) {
|
||||
sInstance = new BiometricsFingerprint();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
fingerprint_device_t* BiometricsFingerprint::openHal() {
|
||||
int err;
|
||||
const hw_module_t *hw_mdl = NULL;
|
||||
ALOGE("Opening fingerprint hal library...");
|
||||
const hw_module_t *hw_mdl = nullptr;
|
||||
ALOGD("Opening fingerprint hal library...");
|
||||
if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) {
|
||||
ALOGE("Can't open fingerprint HW Module, error: %d", err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (hw_mdl == NULL) {
|
||||
if (hw_mdl == nullptr) {
|
||||
ALOGE("No valid fingerprint module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fingerprint_module_t const *module =
|
||||
reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
|
||||
if (module->common.methods->open == NULL) {
|
||||
if (module->common.methods->open == nullptr) {
|
||||
ALOGE("No valid open method");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hw_device_t *device = NULL;
|
||||
hw_device_t *device = nullptr;
|
||||
|
||||
if (0 != (err = module->common.methods->open(hw_mdl, NULL, &device))) {
|
||||
if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) {
|
||||
ALOGE("Can't open fingerprint methods, error: %d", err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (kVersion != device->version) {
|
||||
// enforce version on new devices because of HIDL@2.1 translation layer
|
||||
ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
|
||||
return 0; // enforce this on new devices because of HIDL translation layer
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fingerprint_device_t* fp_device =
|
||||
@@ -240,23 +249,67 @@ IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new BiometricsFingerprint(fp_device);
|
||||
return fp_device;
|
||||
}
|
||||
|
||||
void BiometricsFingerprint::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {
|
||||
if (auth_token != nullptr && auth_token_length > 0) {
|
||||
// TODO: cache service?
|
||||
sp<IServiceManager> sm = android::defaultServiceManager();
|
||||
sp<::android::IBinder> binder = sm->getService(String16("android.security.keystore"));
|
||||
sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
|
||||
if (service != nullptr) {
|
||||
auto ret = service->addAuthToken(auth_token, auth_token_length);
|
||||
if (!ret.isOk()) {
|
||||
ALOGE("Failure sending auth token to KeyStore: %" PRId32, int32_t(ret));
|
||||
void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
|
||||
BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
|
||||
BiometricsFingerprint::getInstance());
|
||||
if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
|
||||
ALOGE("Receiving callbacks before the client callback is registered.");
|
||||
return;
|
||||
}
|
||||
const uint64_t devId = reinterpret_cast<uint64_t>(thisPtr->mDevice);
|
||||
switch (msg->type) {
|
||||
case FINGERPRINT_ERROR: {
|
||||
int32_t vendorCode = 0;
|
||||
FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
|
||||
thisPtr->mClientCallback->onError(devId, result, vendorCode);
|
||||
}
|
||||
} else {
|
||||
ALOGE("Unable to communicate with KeyStore");
|
||||
}
|
||||
break;
|
||||
case FINGERPRINT_ACQUIRED: {
|
||||
int32_t vendorCode = 0;
|
||||
FingerprintAcquiredInfo result =
|
||||
VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
|
||||
thisPtr->mClientCallback->onAcquired(devId, result, vendorCode);
|
||||
}
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_ENROLLING:
|
||||
thisPtr->mClientCallback->onEnrollResult(devId,
|
||||
msg->data.enroll.finger.fid,
|
||||
msg->data.enroll.finger.gid,
|
||||
msg->data.enroll.samples_remaining);
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_REMOVED:
|
||||
thisPtr->mClientCallback->onRemoved(devId,
|
||||
msg->data.removed.finger.fid,
|
||||
msg->data.removed.finger.gid,
|
||||
msg->data.removed.remaining_templates);
|
||||
break;
|
||||
case FINGERPRINT_AUTHENTICATED:
|
||||
if (msg->data.authenticated.finger.fid != 0) {
|
||||
const uint8_t* hat =
|
||||
reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
|
||||
const hidl_vec<uint8_t> token(
|
||||
std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
|
||||
thisPtr->mClientCallback->onAuthenticated(devId,
|
||||
msg->data.authenticated.finger.fid,
|
||||
msg->data.authenticated.finger.gid,
|
||||
token);
|
||||
} else {
|
||||
// Not a recognized fingerprint
|
||||
thisPtr->mClientCallback->onAuthenticated(devId,
|
||||
msg->data.authenticated.finger.fid,
|
||||
msg->data.authenticated.finger.gid,
|
||||
hidl_vec<uint8_t>());
|
||||
}
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_ENUMERATING:
|
||||
thisPtr->mClientCallback->onEnumerate(devId,
|
||||
msg->data.enumerated.finger.fid,
|
||||
msg->data.enumerated.finger.gid,
|
||||
msg->data.enumerated.remaining_templates);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ using ::android::sp;
|
||||
|
||||
struct BiometricsFingerprint : public IBiometricsFingerprint {
|
||||
public:
|
||||
BiometricsFingerprint(fingerprint_device_t *device);
|
||||
BiometricsFingerprint();
|
||||
~BiometricsFingerprint();
|
||||
|
||||
// Method to wrap legacy HAL with BiometricsFingerprint class
|
||||
@@ -60,68 +60,17 @@ public:
|
||||
Return<RequestStatus> remove(uint32_t gid, uint32_t fid) override;
|
||||
Return<RequestStatus> setActiveGroup(uint32_t gid, const hidl_string& storePath) override;
|
||||
Return<RequestStatus> authenticate(uint64_t operationId, uint32_t gid) override;
|
||||
static void notify(const fingerprint_msg_t *msg) {
|
||||
if (mClientCallback == nullptr) {
|
||||
ALOGE("Receiving callbacks before the client callback is registered.");
|
||||
return;
|
||||
}
|
||||
const uint64_t devId = reinterpret_cast<uint64_t>(sDevice);
|
||||
switch (msg->type) {
|
||||
case FINGERPRINT_ERROR: {
|
||||
int32_t vendorCode = 0;
|
||||
FingerprintError result =
|
||||
VendorErrorFilter(msg->data.error, &vendorCode);
|
||||
mClientCallback->onError(devId, result, vendorCode);
|
||||
}
|
||||
break;
|
||||
case FINGERPRINT_ACQUIRED: {
|
||||
int32_t vendorCode = 0;
|
||||
FingerprintAcquiredInfo result =
|
||||
VendorAcquiredFilter(msg->data.acquired.acquired_info,
|
||||
&vendorCode);
|
||||
mClientCallback->onAcquired(devId, result, vendorCode);
|
||||
}
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_ENROLLING:
|
||||
mClientCallback->onEnrollResult(devId,
|
||||
msg->data.enroll.finger.fid,
|
||||
msg->data.enroll.finger.gid,
|
||||
msg->data.enroll.samples_remaining);
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_REMOVED:
|
||||
mClientCallback->onRemoved(devId,
|
||||
msg->data.removed.finger.fid,
|
||||
msg->data.removed.finger.gid,
|
||||
msg->data.removed.remaining_templates);
|
||||
break;
|
||||
case FINGERPRINT_AUTHENTICATED:
|
||||
if (msg->data.authenticated.finger.fid != 0) {
|
||||
const uint8_t* hat =
|
||||
reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
|
||||
notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
|
||||
}
|
||||
mClientCallback->onAuthenticated(devId,
|
||||
msg->data.authenticated.finger.fid,
|
||||
msg->data.authenticated.finger.gid);
|
||||
break;
|
||||
case FINGERPRINT_TEMPLATE_ENUMERATING:
|
||||
mClientCallback->onEnumerate(devId,
|
||||
msg->data.enumerated.finger.fid,
|
||||
msg->data.enumerated.finger.gid,
|
||||
msg->data.enumerated.remaining_templates);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Return<RequestStatus> ErrorFilter(int32_t error);
|
||||
static void notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length);
|
||||
static FingerprintError VendorErrorFilter(int32_t error,
|
||||
int32_t* vendorCode);
|
||||
static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error,
|
||||
int32_t* vendorCode);
|
||||
static sp<IBiometricsFingerprintClientCallback> mClientCallback;
|
||||
static fingerprint_device_t* openHal();
|
||||
static void notify(const fingerprint_msg_t *msg); /* Static callback for legacy HAL implementation */
|
||||
static Return<RequestStatus> ErrorFilter(int32_t error);
|
||||
static FingerprintError VendorErrorFilter(int32_t error, int32_t* vendorCode);
|
||||
static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
|
||||
static BiometricsFingerprint* sInstance;
|
||||
|
||||
sp<IBiometricsFingerprintClientCallback> mClientCallback;
|
||||
fingerprint_device_t *mDevice;
|
||||
static fingerprint_device_t *sDevice; // TODO: allow multiple drivers
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
Reference in New Issue
Block a user