summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Kaye <jameskaye@google.com>2015-09-10 21:32:31 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-09-10 21:32:31 +0000
commitb82a006cf7db1d3790272279eeaa066827d5bf81 (patch)
tree93c59cbd22653076d3039d9142fe78d1b52a293e
parent00c1f48e2afff6a0a605290d5fd893a63a700a7a (diff)
parenta01bcfd5af2254f7458ba36d30858d0b3e1a9bb1 (diff)
downloadandroid_device_generic_goldfish-b82a006cf7db1d3790272279eeaa066827d5bf81.tar.gz
android_device_generic_goldfish-b82a006cf7db1d3790272279eeaa066827d5bf81.tar.bz2
android_device_generic_goldfish-b82a006cf7db1d3790272279eeaa066827d5bf81.zip
Merge "Support removing a fingerprint" into mnc-dev
-rw-r--r--fingerprint/fingerprint.c706
1 files changed, 466 insertions, 240 deletions
diff --git a/fingerprint/fingerprint.c b/fingerprint/fingerprint.c
index c3dc787..97b6d73 100644
--- a/fingerprint/fingerprint.c
+++ b/fingerprint/fingerprint.c
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-#define FINGERPRINT_LISTEN_SERVICE_NAME "fingerprintlisten"
-#define FINGERPRINT_TXT_FILENAME "/data/fingerprint.txt"
-
#define LOG_TAG "FingerprintHal"
-#define MAX_NUM_FINGERS 32
#include <errno.h>
#include <endian.h>
@@ -30,239 +26,145 @@
#include <hardware/fingerprint.h>
#include <hardware/qemud.h>
+#define FINGERPRINT_LISTEN_SERVICE_NAME "fingerprintlisten"
+#define FINGERPRINT_FILENAME \
+ "/data/system/users/0/fpdata/emulator_fingerprint_storage.bin"
+#define MAX_COMM_CHARS 128
+#define MAX_COMM_ERRORS 8
+#define MAX_NUM_FINGERS 20
+#define MAX_FID_VALUE 0x7FFFFFFF // Arbitrary limit
+
typedef enum worker_state_t {
- STATE_ENROLL = 1,
- STATE_SCAN = 2,
- STATE_IDLE = 3,
- STATE_EXIT = 4
+ STATE_IDLE = 0,
+ STATE_ENROLL,
+ STATE_SCAN,
+ STATE_EXIT
} worker_state_t;
typedef struct worker_thread_t {
pthread_t thread;
- pthread_mutex_t mutex;
- int request;
worker_state_t state;
- int fingerid;
- int finger_is_on;
- int all_fingerids[MAX_NUM_FINGERS];
- uint64_t all_secureids[MAX_NUM_FINGERS];
- uint64_t all_authenids[MAX_NUM_FINGERS];
- int num_fingers_enrolled;
- FILE *fp_write;;
+ uint64_t secureid[MAX_NUM_FINGERS];
+ uint64_t authenid[MAX_NUM_FINGERS];
} worker_thread_t;
-typedef struct emu_fingerprint_hal_device_t {
- fingerprint_device_t device; //inheritance
+typedef struct qemu_fingerprint_device_t {
+ fingerprint_device_t device; // "inheritance"
worker_thread_t listener;
uint64_t op_id;
uint64_t challenge;
- uint64_t secure_user_id;
uint64_t user_id;
+ uint64_t group_id;
+ uint64_t secure_user_id;
uint64_t authenticator_id;
+ int qchanfd;
pthread_mutex_t lock;
-} emu_fingerprint_hal_device_t;
+} qemu_fingerprint_device_t;
-static uint64_t get_64bit_rand() {
- return (((uint64_t) rand()) << 32) | ((uint64_t) rand());
-}
+/******************************************************************************/
-static void destroyListenerThread(emu_fingerprint_hal_device_t* dev)
-{
- pthread_join(dev->listener.thread, NULL);
- pthread_mutex_destroy(&dev->listener.mutex);
-}
+static void saveFingerprint(worker_thread_t* listener, int idx) {
+ ALOGD("----------------> %s -----------------> idx %d", __FUNCTION__, idx);
-bool finger_already_enrolled(emu_fingerprint_hal_device_t* dev) {
- int i;
- for (i = 0; i < dev->listener.num_fingers_enrolled; ++ i) {
- if (dev->listener.fingerid == dev->listener.all_fingerids[i % MAX_NUM_FINGERS]) {
- dev->secure_user_id = dev->listener.all_secureids[i % MAX_NUM_FINGERS];
- dev->authenticator_id = dev->listener.all_authenids[i % MAX_NUM_FINGERS];
- return true;
- }
+ // Save fingerprints to file
+ FILE* fp = fopen(FINGERPRINT_FILENAME, "r+"); // write but don't truncate
+ if (fp == NULL) {
+ ALOGE("Could not open fingerprints storage at %s; "
+ "fingerprints won't be saved",
+ FINGERPRINT_FILENAME);
+ perror("Failed to open file");
+ return;
}
- return false;
-}
-static void save_fingerid(FILE* fp, int fingerid, uint64_t secureid, uint64_t authenid) {
- if (!fp) return;
- fprintf(fp, " %d %" PRIu64 " %" PRIu64, fingerid, secureid, authenid);
- fflush(fp);
-}
+ ALOGD("Write fingerprint[%d] (0x%" PRIx64 ",0x%" PRIx64 ")", idx,
+ listener->secureid[idx], listener->authenid[idx]);
-static void listener_send_notice(emu_fingerprint_hal_device_t* dev)
-{
- fingerprint_msg_t message = {0};
- bool is_authentication = false;
- bool is_valid_finger = false;
- pthread_mutex_lock(&dev->listener.mutex);
- if (dev->listener.state == STATE_ENROLL) {
- message.type = FINGERPRINT_TEMPLATE_ENROLLING;
- message.data.enroll.finger.fid = dev->listener.fingerid;
- message.data.enroll.samples_remaining = 0;
- dev->authenticator_id = get_64bit_rand();
- dev->listener.state = STATE_SCAN;
- if (!finger_already_enrolled(dev)) {
- dev->listener.all_fingerids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = dev->listener.fingerid;
- dev->listener.all_secureids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = dev->secure_user_id;
- dev->listener.all_authenids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = dev->authenticator_id;
- ++ dev->listener.num_fingers_enrolled;
- save_fingerid(dev->listener.fp_write, dev->listener.fingerid, dev->secure_user_id, dev->authenticator_id);
- is_valid_finger = true;
- }
- } else {
- is_authentication = true;
- is_valid_finger = finger_already_enrolled(dev);
- message.type = FINGERPRINT_AUTHENTICATED;
- message.data.authenticated.finger.gid = 0;
- message.data.authenticated.finger.fid = is_valid_finger ? dev->listener.fingerid : 0;
- message.data.authenticated.hat.version = HW_AUTH_TOKEN_VERSION;
- message.data.authenticated.hat.authenticator_type = htobe32(HW_AUTH_FINGERPRINT);
- message.data.authenticated.hat.challenge = dev->op_id;
- message.data.authenticated.hat.authenticator_id = dev->authenticator_id;
- message.data.authenticated.hat.user_id = dev->secure_user_id;
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- message.data.authenticated.hat.timestamp =
- htobe64((uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
- }
- pthread_mutex_unlock(&dev->listener.mutex);
-
- pthread_mutex_lock(&dev->lock);
- if (is_authentication) {
- fingerprint_msg_t acquired_message = {0};
- acquired_message.type = FINGERPRINT_ACQUIRED;
- message.data.acquired.acquired_info = FINGERPRINT_ACQUIRED_GOOD;
- dev->device.notify(&acquired_message);
+ if (fseek(fp, (idx) * sizeof(uint64_t), SEEK_SET) < 0) {
+ ALOGE("Failed while seeking for fingerprint[%d] in emulator storage",
+ idx);
+ fclose(fp);
+ return;
}
- if (is_valid_finger || is_authentication) {
- dev->device.notify(&message);
+ int ns = fwrite(&listener->secureid[idx], sizeof(uint64_t), 1, fp);
+ if (fseek(fp, (MAX_NUM_FINGERS + idx) * sizeof(uint64_t), SEEK_SET) < 0) {
+ ALOGE("Failed while seeking for fingerprint[%d] in emulator storage",
+ idx);
+ fclose(fp);
+ return;
}
- pthread_mutex_unlock(&dev->lock);
-}
+ int na = fwrite(&listener->authenid[idx], sizeof(uint64_t), 1, fp);
+ if (ns != 1 || na != 1)
+ ALOGW("Corrupt emulator fingerprints storage; could not save "
+ "fingerprints");
-static void* listenerFunction(void* data)
-{
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) data;
+ fclose(fp);
- int fd = qemud_channel_open(FINGERPRINT_LISTEN_SERVICE_NAME);
- if (fd < 0) {
- ALOGE("listener cannot open fingerprint listener service exit");
- return NULL;
- }
+ return;
+}
- const char* cmd = "listen";
- if (qemud_channel_send(fd, cmd, strlen(cmd)) < 0) {
- ALOGE("cannot write fingerprint 'listen' to host");
- return NULL;
+static void loadFingerprints(worker_thread_t* listener) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ FILE* fp = fopen(FINGERPRINT_FILENAME, "a+"); // so we can create if empty
+ if (fp == NULL) {
+ ALOGE("Could not load fingerprints from storage at %s; "
+ "it has not yet been created.",
+ FINGERPRINT_FILENAME);
+ perror("Failed to open/create file");
+ return;
}
- int i;
- for (i = 0; i < MAX_NUM_FINGERS; ++ i) {
- dev->listener.all_fingerids[i] = 0;
- }
- //read registered fingerprint ids from /data/local/fingerprint.txt
- //TODO: store it in a better location
- dev->listener.num_fingers_enrolled = 0;
- FILE* fp_stored = fopen(FINGERPRINT_TXT_FILENAME, "r");
- if (fp_stored) {
- while (1) {
- int fingerid = 0;
- uint64_t secureid = 0;
- uint64_t authenid = 0;
- if(fscanf(fp_stored, "%d %" SCNu64 " %" SCNu64, &fingerid, &secureid, &authenid) == 3) {
- dev->listener.all_fingerids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = fingerid;
- dev->listener.all_secureids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = secureid;
- dev->listener.all_authenids[dev->listener.num_fingers_enrolled % MAX_NUM_FINGERS] = authenid;
- ++ dev->listener.num_fingers_enrolled;
- } else {
- break;
- }
- }
- fclose(fp_stored);
- }
+ int ns = fread(listener->secureid, MAX_NUM_FINGERS * sizeof(uint64_t), 1,
+ fp);
+ int na = fread(listener->authenid, MAX_NUM_FINGERS * sizeof(uint64_t), 1,
+ fp);
+ if (ns != 1 || na != 1)
+ ALOGW("Corrupt emulator fingerprints storage (read %d+%db)", ns, na);
- dev->listener.fp_write = fopen(FINGERPRINT_TXT_FILENAME, "a");
+ int i = 0;
+ for (i = 0; i < MAX_NUM_FINGERS; i++)
+ ALOGD("Read fingerprint %d (0x%" PRIx64 ",0x%" PRIx64 ")", i,
+ listener->secureid[i], listener->authenid[i]);
- char buffer[128];
- int fingerid=-1;
- int size;
- while (1) {
- //simply listen in blocking mode
- if ((size = qemud_channel_recv(fd, buffer, sizeof buffer - 1)) >0) {
- buffer[size] = '\0';
- if (sscanf(buffer, "on:%d", &fingerid) == 1) {
- if (fingerid > 0 ) {
- dev->listener.fingerid = fingerid;
- dev->listener.finger_is_on = 1;
- ALOGD("got finger %d", fingerid);
- listener_send_notice(dev);
- ALOGD("send notice finger %d", fingerid);
- }
- else {
- ALOGE("finger id should be positive");
- }
- } else if (strncmp("off", buffer, 3) == 0) {
- dev->listener.finger_is_on = 0;
- ALOGD("finger off %d", fingerid);
- } else {
- ALOGE("error: '%s'", buffer);
- }
- } else {
- ALOGE("receive failure");
- // return NULL;
- }
- //TODO: check for request to exit thread
- }
+ fclose(fp);
- ALOGD("listener exit");
- return NULL;
+ return;
}
-static void createListenerThread(emu_fingerprint_hal_device_t* dev)
-{
- pthread_mutex_init(&dev->listener.mutex, NULL);
- pthread_create(&dev->listener.thread, NULL, listenerFunction, dev);
-}
+/******************************************************************************/
-static int fingerprint_close(hw_device_t *dev)
-{
- if (dev) {
- destroyListenerThread((emu_fingerprint_hal_device_t*) dev);
- free(dev);
- return 0;
- } else {
- return -1;
- }
+static uint64_t get_64bit_rand() {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ uint64_t r = (((uint64_t)rand()) << 32) | ((uint64_t)rand());
+ return r != 0 ? r : 1;
}
-static void setListenerState(emu_fingerprint_hal_device_t* dev, worker_state_t state) {
- pthread_mutex_lock(&dev->listener.mutex);
- dev->listener.state = state;
- pthread_mutex_unlock(&dev->listener.mutex);
-}
+static uint64_t fingerprint_get_auth_id(struct fingerprint_device* device) {
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ uint64_t authenticator_id = 0;
+ pthread_mutex_lock(&qdev->lock);
+ authenticator_id = qdev->authenticator_id;
+ pthread_mutex_unlock(&qdev->lock);
-static uint64_t fingerprint_get_auth_id(struct fingerprint_device __unused *device) {
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) device;
- return dev->authenticator_id;
+ return authenticator_id;
}
static int fingerprint_set_active_group(struct fingerprint_device __unused *device, uint32_t gid,
const char *path) {
- // TODO: implements me
+ ALOGW("Setting active finger group not implemented");
return 0;
}
-static int fingerprint_authenticate(struct fingerprint_device __unused *device,
- uint64_t __unused operation_id, __unused uint32_t gid)
+static int fingerprint_authenticate(struct fingerprint_device *device,
+ uint64_t operation_id, __unused uint32_t gid)
{
- ALOGD("fingerprint_authenticate");
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+
+ pthread_mutex_lock(&qdev->lock);
+ qdev->op_id = operation_id;
+ qdev->listener.state = STATE_SCAN;
+ pthread_mutex_unlock(&qdev->lock);
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) device;
- pthread_mutex_lock(&dev->lock);
- dev->op_id = operation_id;
- pthread_mutex_unlock(&dev->lock);
- setListenerState(dev, STATE_SCAN);
return 0;
}
@@ -271,11 +173,15 @@ static int fingerprint_enroll(struct fingerprint_device *device,
uint32_t __unused gid,
uint32_t __unused timeout_sec) {
ALOGD("fingerprint_enroll");
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) device;
- if (hat && hat->challenge == dev->challenge) {
+ qemu_fingerprint_device_t* dev = (qemu_fingerprint_device_t*)device;
+ if (!hat) {
+ ALOGW("%s: null auth token", __func__);
+ return -EPROTONOSUPPORT;
+ }
+ if (hat->challenge == dev->challenge) {
dev->secure_user_id = hat->user_id;
} else {
- ALOGW("%s: invalid or null auth token", __func__);
+ ALOGW("%s: invalid auth token", __func__);
}
if (hat->version != HW_AUTH_TOKEN_VERSION) {
@@ -287,81 +193,401 @@ static int fingerprint_enroll(struct fingerprint_device *device,
dev->user_id = hat->user_id;
- // TODO: store enrolled fingerprints, authenticator id, and secure_user_id
- setListenerState(dev, STATE_ENROLL);
+ pthread_mutex_lock(&dev->lock);
+ dev->listener.state = STATE_ENROLL;
+ pthread_mutex_unlock(&dev->lock);
+
+ // fingerprint id, authenticator id, and secure_user_id
+ // will be stored by worked thread
+
return 0;
}
static uint64_t fingerprint_pre_enroll(struct fingerprint_device *device) {
- ALOGD("fingerprint_pre_enroll");
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) device;
- dev->challenge = get_64bit_rand();
- return dev->challenge;
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ uint64_t challenge = 0;
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+
+ challenge = get_64bit_rand();
+
+ pthread_mutex_lock(&qdev->lock);
+ qdev->challenge = challenge;
+ pthread_mutex_unlock(&qdev->lock);
+
+ return challenge;
+}
+
+static int fingerprint_post_enroll(struct fingerprint_device* device) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+
+ pthread_mutex_lock(&qdev->lock);
+ qdev->challenge = 0;
+ pthread_mutex_unlock(&qdev->lock);
+
+ return 0;
}
-static int fingerprint_cancel(struct fingerprint_device __unused *device) {
- ALOGD("fingerprint_cancel");
- emu_fingerprint_hal_device_t* dev = (emu_fingerprint_hal_device_t*) device;
- setListenerState(dev, STATE_IDLE);
+static int fingerprint_cancel(struct fingerprint_device *device) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+
+ fingerprint_msg_t msg = {0};
+ msg.type = FINGERPRINT_ERROR;
+ msg.data.error = FINGERPRINT_ERROR_CANCELED;
+
+ pthread_mutex_lock(&qdev->lock);
+ qdev->listener.state = STATE_IDLE;
+ pthread_mutex_unlock(&qdev->lock);
+
+ device->notify(&msg);
+
return 0;
}
static int fingerprint_enumerate(struct fingerprint_device *device,
fingerprint_finger_id_t *results, uint32_t *max_size) {
- // TODO: implement me
- return 0;
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ if (device == NULL || results == NULL || max_size == NULL) {
+ ALOGE("Cannot enumerate saved fingerprints with uninitialized params");
+ return -1;
+ }
+
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+ unsigned int i = 0;
+ int num = 0;
+ for (i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (qdev->listener.secureid[i] != 0 ||
+ qdev->listener.authenid[i] != 0) {
+ ALOGD("ENUM: Fingerprint [%d] = 0x%" PRIx64 ",%" PRIx64, i,
+ qdev->listener.secureid[i], qdev->listener.authenid[i]);
+ num++;
+ }
+ }
+
+ return num;
}
-static int fingerprint_remove(struct fingerprint_device __unused *dev,
- uint32_t __unused gid, uint32_t __unused fid) {
- // TODO: implement enroll and remove, and set dev->authenticator_id = 0 when no FPs enrolled
- return FINGERPRINT_ERROR;
+static int fingerprint_remove(struct fingerprint_device *device,
+ uint32_t __unused gid, uint32_t fid) {
+ int idx = 0;
+ fingerprint_msg_t msg = {0};
+ ALOGD("----------------> %s -----------------> fid %d", __FUNCTION__, fid);
+ if (device == NULL) {
+ ALOGE("Can't remove fingerprint (gid=%d, fid=%d); "
+ "device not initialized properly",
+ gid, fid);
+ return -1;
+ }
+
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+
+ if (fid == 0) {
+ // Delete all fingerprints
+ // I'll do this one at a time, so I am not
+ // holding the mutext during the notification
+ bool listIsEmpty;
+ do {
+ pthread_mutex_lock(&qdev->lock);
+ listIsEmpty = true; // Haven't seen a valid entry yet
+ for (idx = 0; idx < MAX_NUM_FINGERS; idx++) {
+ uint32_t theFid = qdev->listener.authenid[idx];
+ if (theFid != 0) {
+ // Delete this entry
+ qdev->listener.secureid[idx] = 0;
+ qdev->listener.authenid[idx] = 0;
+ saveFingerprint(&qdev->listener, idx);
+
+ // Send a notification that we deleted this one
+ pthread_mutex_unlock(&qdev->lock);
+ msg.type = FINGERPRINT_TEMPLATE_REMOVED;
+ msg.data.removed.finger.fid = theFid;
+ device->notify(&msg);
+
+ // Because we released the mutex, the list
+ // may have changed. Restart the 'for' loop
+ // after reacquiring the mutex.
+ listIsEmpty = false;
+ break;
+ }
+ } // end for (idx < MAX_NUM_FINGERS)
+ } while (!listIsEmpty);
+ qdev->listener.state = STATE_IDLE;
+ pthread_mutex_unlock(&qdev->lock);
+ } else {
+ // Delete one fingerprint
+ // Look for this finger ID in our table.
+ pthread_mutex_lock(&qdev->lock);
+ for (idx = 0; idx < MAX_NUM_FINGERS; idx++) {
+ if (qdev->listener.authenid[idx] == fid &&
+ qdev->listener.secureid[idx] != 0) {
+ // Found it!
+ break;
+ }
+ }
+ if (idx >= MAX_NUM_FINGERS) {
+ qdev->listener.state = STATE_IDLE;
+ pthread_mutex_unlock(&qdev->lock);
+ ALOGE("Fingerprint ID %d not found", fid);
+ return FINGERPRINT_ERROR;
+ }
+
+ qdev->listener.secureid[idx] = 0;
+ qdev->listener.authenid[idx] = 0;
+ saveFingerprint(&qdev->listener, idx);
+
+ qdev->listener.state = STATE_IDLE;
+ pthread_mutex_unlock(&qdev->lock);
+
+ msg.type = FINGERPRINT_TEMPLATE_REMOVED;
+ msg.data.removed.finger.fid = fid;
+ device->notify(&msg);
+ }
+
+ return 0;
}
static int set_notify_callback(struct fingerprint_device *device,
- fingerprint_notify_t notify) {
- ALOGD("set_notify");
- emu_fingerprint_hal_device_t* dev =(emu_fingerprint_hal_device_t*) device;
- pthread_mutex_lock(&dev->lock);
+ fingerprint_notify_t notify) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ if (device == NULL || notify == NULL) {
+ ALOGE("Failed to set notify callback @ %p for fingerprint device %p",
+ device, notify);
+ return -1;
+ }
+
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+ pthread_mutex_lock(&qdev->lock);
+ qdev->listener.state = STATE_IDLE;
device->notify = notify;
+ pthread_mutex_unlock(&qdev->lock);
+ ALOGD("fingerprint callback notification set");
+
+ return 0;
+}
+
+static void send_scan_notice(qemu_fingerprint_device_t* qdev, int fid) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+
+ // acquired message
+ fingerprint_msg_t acqu_msg = {0};
+ acqu_msg.type = FINGERPRINT_ACQUIRED;
+ acqu_msg.data.acquired.acquired_info = FINGERPRINT_ACQUIRED_GOOD;
+
+ // authenticated message
+ fingerprint_msg_t auth_msg = {0};
+ auth_msg.type = FINGERPRINT_AUTHENTICATED;
+ auth_msg.data.authenticated.finger.fid = fid;
+ auth_msg.data.authenticated.finger.gid = 0; // unused
+ auth_msg.data.authenticated.hat.version = HW_AUTH_TOKEN_VERSION;
+ auth_msg.data.authenticated.hat.authenticator_type =
+ htobe32(HW_AUTH_FINGERPRINT);
+ auth_msg.data.authenticated.hat.challenge = qdev->op_id;
+ auth_msg.data.authenticated.hat.authenticator_id = qdev->authenticator_id;
+ auth_msg.data.authenticated.hat.user_id = qdev->secure_user_id;
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ auth_msg.data.authenticated.hat.timestamp =
+ htobe64((uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
+
+ // pthread_mutex_lock(&qdev->lock);
+ qdev->device.notify(&acqu_msg);
+ qdev->device.notify(&auth_msg);
+ // pthread_mutex_unlock(&qdev->lock);
+
+ return;
+}
+
+static void send_enroll_notice(qemu_fingerprint_device_t* qdev, int fid) {
+ ALOGD("----------------> %s -----------------> fid %d", __FUNCTION__, fid);
+
+ if (fid == 0) {
+ ALOGD("Fingerprint ID is zero (invalid)");
+ return;
+ }
+ if (qdev->secure_user_id == 0) {
+ ALOGD("Secure user ID is zero (invalid)");
+ return;
+ }
+
+ // Find an available entry in the table
+ pthread_mutex_lock(&qdev->lock);
+ int idx = 0;
+ for (idx = 0; idx < MAX_NUM_FINGERS; idx++) {
+ if (qdev->listener.secureid[idx] == 0 ||
+ qdev->listener.authenid[idx] == 0) {
+ // This entry is available
+ break;
+ }
+ }
+ if (idx >= MAX_NUM_FINGERS) {
+ qdev->listener.state = STATE_SCAN;
+ pthread_mutex_unlock(&qdev->lock);
+ ALOGD("Fingerprint ID table is full");
+ return;
+ }
+
+ qdev->listener.secureid[idx] = qdev->secure_user_id;
+ qdev->listener.authenid[idx] = fid;
+ saveFingerprint(&qdev->listener, idx);
+
+ qdev->listener.state = STATE_SCAN;
+ pthread_mutex_unlock(&qdev->lock);
+
+ // LOCKED notification?
+ fingerprint_msg_t msg = {0};
+ msg.type = FINGERPRINT_TEMPLATE_ENROLLING;
+ msg.data.enroll.finger.fid = fid;
+ msg.data.enroll.samples_remaining = 0;
+ qdev->device.notify(&msg);
+
+ return;
+}
+
+static worker_state_t getListenerState(qemu_fingerprint_device_t* dev) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ worker_state_t state = STATE_IDLE;
+
+ pthread_mutex_lock(&dev->lock);
+ state = dev->listener.state;
pthread_mutex_unlock(&dev->lock);
+
+ return state;
+}
+
+static void* listenerFunction(void* data) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)data;
+
+ pthread_mutex_lock(&qdev->lock);
+ qdev->qchanfd = qemud_channel_open(FINGERPRINT_LISTEN_SERVICE_NAME);
+ if (qdev->qchanfd < 0) {
+ ALOGE("listener cannot open fingerprint listener service exit");
+ pthread_mutex_unlock(&qdev->lock);
+ return NULL;
+ }
+ qdev->listener.state = STATE_IDLE;
+ pthread_mutex_unlock(&qdev->lock);
+
+ const char* cmd = "listen";
+ if (qemud_channel_send(qdev->qchanfd, cmd, strlen(cmd)) < 0) {
+ ALOGE("cannot write fingerprint 'listen' to host");
+ return NULL;
+ }
+ int comm_errors = 0;
+ while (getListenerState(qdev) != STATE_EXIT) {
+ int size = 0;
+ int fid = 0;
+ char buffer[MAX_COMM_CHARS] = {0};
+ // will block until a new event happens
+ if ((size = qemud_channel_recv(qdev->qchanfd, buffer,
+ sizeof(buffer) - 1)) > 0) {
+ buffer[size] = '\0';
+ if (sscanf(buffer, "on:%d", &fid) == 1) {
+ if (fid > 0 && fid <= MAX_FID_VALUE) {
+ switch (qdev->listener.state) {
+ case STATE_ENROLL:
+ send_enroll_notice(qdev, fid);
+ break;
+ case STATE_SCAN:
+ send_scan_notice(qdev, fid);
+ break;
+ default:
+ ALOGE("fingerprint event listener at unexpected "
+ "state 0%x",
+ qdev->listener.state);
+ }
+ } else {
+ ALOGE("fingerprintid %d not in valid range [%d, %d] and "
+ "will be "
+ "ignored",
+ fid, 1, MAX_FID_VALUE);
+ continue;
+ }
+ } else if (strncmp("off", buffer, 3) == 0) {
+ // TODO: Nothing to do here ? Looks valid
+ ALOGD("fingerprint ID %d off", fid);
+ } else {
+ ALOGE("Invalid command '%s' to fingerprint listener", buffer);
+ }
+ } else {
+ ALOGE("fingerprint listener receive failure");
+ if (comm_errors > MAX_COMM_ERRORS)
+ break;
+ }
+ }
+
+ ALOGD("Listener exit with %d receive errors", comm_errors);
+ return NULL;
+}
+
+static int fingerprint_close(hw_device_t* device) {
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
+ if (device == NULL) {
+ ALOGE("fingerprint hw device is NULL");
+ return -1;
+ }
+
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
+ pthread_mutex_lock(&qdev->lock);
+ if (qdev->qchanfd != 0)
+ close(qdev->qchanfd); // unblock listener
+ qdev->listener.state = STATE_EXIT;
+ pthread_mutex_unlock(&qdev->lock);
+
+ pthread_join(qdev->listener.thread, NULL);
+ pthread_mutex_destroy(&qdev->lock);
+ free(qdev);
+
return 0;
}
static int fingerprint_open(const hw_module_t* module, const char __unused *id,
hw_device_t** device)
{
+
+ ALOGD("----------------> %s ----------------->", __FUNCTION__);
if (device == NULL) {
ALOGE("NULL device on open");
return -EINVAL;
- } else {
- ALOGD("fingerprint open\n");
}
- emu_fingerprint_hal_device_t *dev = malloc(sizeof(emu_fingerprint_hal_device_t));
- memset(dev, 0, sizeof(emu_fingerprint_hal_device_t));
-
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HARDWARE_MODULE_API_VERSION(2, 0);
- dev->device.common.module = (struct hw_module_t*) module;
- dev->device.common.close = fingerprint_close;
- dev->device.pre_enroll = fingerprint_pre_enroll;
- dev->device.enroll = fingerprint_enroll;
- dev->device.get_authenticator_id = fingerprint_get_auth_id;
- dev->device.set_active_group = fingerprint_set_active_group;
- dev->device.authenticate = fingerprint_authenticate;
- dev->device.cancel = fingerprint_cancel;
- dev->device.enumerate = fingerprint_enumerate;
- dev->device.remove = fingerprint_remove;
- dev->device.set_notify = set_notify_callback;
- dev->device.notify = NULL;
-
- dev->authenticator_id = 0xdeadbeef;
-
- pthread_mutex_init(&dev->lock, NULL);
- createListenerThread(dev);
- *device = (hw_device_t*) dev;
+ qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)calloc(
+ 1, sizeof(qemu_fingerprint_device_t));
+ if (qdev == NULL) {
+ ALOGE("Insufficient memory for virtual fingerprint device");
+ return -ENOMEM;
+ }
+
+ loadFingerprints(&qdev->listener);
+
+ qdev->device.common.tag = HARDWARE_DEVICE_TAG;
+ qdev->device.common.version = HARDWARE_MODULE_API_VERSION(2, 0);
+ qdev->device.common.module = (struct hw_module_t*)module;
+ qdev->device.common.close = fingerprint_close;
+
+ qdev->device.pre_enroll = fingerprint_pre_enroll;
+ qdev->device.enroll = fingerprint_enroll;
+ qdev->device.post_enroll = fingerprint_post_enroll;
+ qdev->device.get_authenticator_id = fingerprint_get_auth_id;
+ qdev->device.set_active_group = fingerprint_set_active_group;
+ qdev->device.authenticate = fingerprint_authenticate;
+ qdev->device.cancel = fingerprint_cancel;
+ qdev->device.enumerate = fingerprint_enumerate;
+ qdev->device.remove = fingerprint_remove;
+ qdev->device.set_notify = set_notify_callback;
+ qdev->device.notify = NULL;
+
+ // init and create listener thread
+ pthread_mutex_init(&qdev->lock, NULL);
+ if (pthread_create(&qdev->listener.thread, NULL, listenerFunction, qdev) !=
+ 0)
+ return -1;
+
+ // "Inheritance" / casting
+ *device = &qdev->device.common;
+
return 0;
}