Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f26c1ac authored by Jim Miller's avatar Jim Miller
Browse files

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
parent c91e7fb9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+92 −39
Original line number Diff line number Diff line
@@ -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);
            }
            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 {
            ALOGE("Unable to communicate with KeyStore");
        }
                // 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;
    }
}

+10 −61
Original line number Diff line number Diff line
@@ -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