diff options
author | bohu <bohu@google.com> | 2015-09-17 18:33:48 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-09-17 18:33:48 +0000 |
commit | c4dfccee900211b2167e879e1e46214b4949ced7 (patch) | |
tree | 8abb459e01c5cf0ddb596f40fb30451fee2f4726 | |
parent | 6f78bde32aa03fdb09087f6a24d62889bcade164 (diff) | |
parent | f20cca78fc06398de0701d0c5bba589c0fe2f738 (diff) | |
download | goldfish-c4dfccee900211b2167e879e1e46214b4949ced7.tar.gz |
am f20cca78: am 948dfb6e: emulator-fingerprint: Exit listener thread on HAL close
* commit 'f20cca78fc06398de0701d0c5bba589c0fe2f738':
emulator-fingerprint: Exit listener thread on HAL close
-rw-r--r-- | fingerprint/fingerprint.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/fingerprint/fingerprint.c b/fingerprint/fingerprint.c index 0b4ca7f8..baa7ad6c 100644 --- a/fingerprint/fingerprint.c +++ b/fingerprint/fingerprint.c @@ -37,6 +37,8 @@ #include <hardware/fingerprint.h> #include <hardware/qemud.h> +#include <poll.h> + #define FINGERPRINT_LISTEN_SERVICE_NAME "fingerprintlisten" #define FINGERPRINT_FILENAME \ "/data/system/users/0/fpdata/emulator_fingerprint_storage.bin" @@ -509,7 +511,7 @@ static void send_enroll_notice(qemu_fingerprint_device_t* qdev, int fid) { } static worker_state_t getListenerState(qemu_fingerprint_device_t* dev) { - ALOGD("----------------> %s ----------------->", __FUNCTION__); + ALOGV("----------------> %s ----------------->", __FUNCTION__); worker_state_t state = STATE_IDLE; pthread_mutex_lock(&dev->lock); @@ -559,14 +561,59 @@ static void* listenerFunction(void* data) { const char* cmd = "listen"; if (qemud_channel_send(qdev->qchanfd, cmd, strlen(cmd)) < 0) { ALOGE("cannot write fingerprint 'listen' to host"); - return NULL; + goto done_quiet; } + int comm_errors = 0; - while (getListenerState(qdev) != STATE_EXIT) { + struct pollfd pfd = { + .fd = qdev->qchanfd, + .events = POLLIN, + }; + while (1) { int size = 0; int fid = 0; char buffer[MAX_COMM_CHARS] = {0}; - // will block until a new event happens + bool disconnected = false; + while (1) { + if (getListenerState(qdev) == STATE_EXIT) { + ALOGD("Received request to exit listener thread"); + goto done; + } + + // Reset revents before poll() (just to be safe) + pfd.revents = 0; + + // Poll qemud channel for 5 seconds + // TODO: Eliminate the timeout so that polling can be interrupted + // instantly. One possible solution is to follow the example of + // android::Looper ($AOSP/system/core/include/utils/Looper.h and + // $AOSP/system/core/libutils/Looper.cpp), which makes use of an + // additional file descriptor ("wake event fd"). + int nfds = poll(&pfd, 1, 5000); + if (nfds < 0) { + ALOGE("Could not poll qemud channel: %s", strerror(errno)); + goto done; + } + + if (!nfds) { + // poll() timed out - try again + continue; + } + + // assert(nfds == 1) + if (pfd.revents & POLLIN) { + // Input data being available doesn't rule out a disconnection + disconnected = pfd.revents & (POLLERR | POLLHUP); + break; // Exit inner while loop + } else { + // Some event(s) other than "input data available" occurred, + // i.e. POLLERR or POLLHUP, indicating a disconnection + ALOGW("Lost connection to qemud channel"); + goto done; + } + } + + // Shouldn't block since we were just notified of a POLLIN event if ((size = qemud_channel_recv(qdev->qchanfd, buffer, sizeof(buffer) - 1)) > 0) { buffer[size] = '\0'; @@ -597,6 +644,11 @@ static void* listenerFunction(void* data) { } else { ALOGE("Invalid command '%s' to fingerprint listener", buffer); } + + if (disconnected) { + ALOGW("Connection to qemud channel has been lost"); + break; + } } else { ALOGE("fingerprint listener receive failure"); if (comm_errors > MAX_COMM_ERRORS) @@ -604,7 +656,10 @@ static void* listenerFunction(void* data) { } } +done: ALOGD("Listener exit with %d receive errors", comm_errors); +done_quiet: + close(qdev->qchanfd); return NULL; } @@ -617,8 +672,7 @@ static int fingerprint_close(hw_device_t* device) { qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device; pthread_mutex_lock(&qdev->lock); - if (qdev->qchanfd != 0) - close(qdev->qchanfd); // unblock listener + // Ask listener thread to exit qdev->listener.state = STATE_EXIT; pthread_mutex_unlock(&qdev->lock); |