Looper.cpp revision 8d15c74d50fd01d6e63970aadd261a9d3bed27e7
17901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown//
27901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Copyright 2010 The Android Open Source Project
37901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown//
47901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// A looper implementation based on epoll().
57901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown//
67901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define LOG_TAG "Looper"
77901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
87901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown//#define LOG_NDEBUG 0
97901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Debugs poll and wake interactions.
117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define DEBUG_POLL_AND_WAKE 0
127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Debugs callback registration and invocation.
147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define DEBUG_CALLBACKS 0
157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <cutils/log.h>
177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <utils/Looper.h>
187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <utils/Timers.h>
197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <unistd.h>
217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <fcntl.h>
227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownnamespace android {
257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Hint for number of file descriptors to be associated with the epoll instance.
287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownstatic const int EPOLL_SIZE_HINT = 8;
297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Maximum number of file descriptors for which to retrieve poll events each iteration.
317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownstatic const int EPOLL_MAX_EVENTS = 16;
328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
34d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
35d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_key_t gTLSKey = 0;
36d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown
377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::Looper(bool allowNonCallbacks) :
387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mAllowNonCallbacks(allowNonCallbacks),
397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mResponseIndex(0) {
407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int wakeFds[2];
417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int result = pipe(wakeFds);
427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mWakeReadPipeFd = wakeFds[0];
457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mWakeWritePipeFd = wakeFds[1];
467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
558d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
568d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    // Allocate the epoll instance and register the wake pipe.
578d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
588d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
598d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    struct epoll_event eventItem;
61d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    eventItem.events = EPOLLIN;
637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    eventItem.data.fd = mWakeReadPipeFd;
647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else
688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    // Add the wake pipe to the head of the request list with a null callback.
698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    struct pollfd requestedFd;
708d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    requestedFd.fd = mWakeReadPipeFd;
718d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    requestedFd.events = POLLIN;
728d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mRequestedFds.push(requestedFd);
738d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
748d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    Request request;
758d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.fd = mWakeReadPipeFd;
768d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.callback = NULL;
778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.ident = 0;
788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.data = NULL;
798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mRequests.push(request);
808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mPolling = false;
828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mWaiters = 0;
838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS
868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mPendingWakeTime = -1;
878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mPendingWakeCount = 0;
888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledWakeCycles = 0;
898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledWakeCountSum = 0;
908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledWakeLatencySum = 0;
918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledPolls = 0;
938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledZeroPollCount = 0;
948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledZeroPollLatencySum = 0;
958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledTimeoutPollCount = 0;
968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledTimeoutPollLatencySum = 0;
978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::~Looper() {
1017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mWakeReadPipeFd);
1027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mWakeWritePipeFd);
1038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
1047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mEpollFd);
1058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
1067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
108d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownvoid Looper::initTLSKey() {
109d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    int result = pthread_key_create(& gTLSKey, threadDestructor);
110d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
111d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown}
112d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown
1137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::threadDestructor(void *st) {
1147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    Looper* const self = static_cast<Looper*>(st);
1157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (self != NULL) {
1167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        self->decStrong((void*)threadDestructor);
1177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::setForThread(const sp<Looper>& looper) {
1217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
1227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper != NULL) {
1247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        looper->incStrong((void*)threadDestructor);
1257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
127d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    pthread_setspecific(gTLSKey, looper.get());
1287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (old != NULL) {
1307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        old->decStrong((void*)threadDestructor);
1317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::getForThread() {
135d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    int result = pthread_once(& gTLSOnce, initTLSKey);
136d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
1377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
138d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    return (Looper*)pthread_getspecific(gTLSKey);
1397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::prepare(int opts) {
1427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
1437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    sp<Looper> looper = Looper::getForThread();
1447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper == NULL) {
1457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        looper = new Looper(allowNonCallbacks);
1467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        Looper::setForThread(looper);
1477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
1497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        LOGW("Looper already prepared for this thread with a different value for the "
1507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
1517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return looper;
1537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownbool Looper::getAllowNonCallbacks() const {
1567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return mAllowNonCallbacks;
1577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
1607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int result = 0;
1617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    for (;;) {
1627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        while (mResponseIndex < mResponses.size()) {
1637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            const Response& response = mResponses.itemAt(mResponseIndex++);
1647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (! response.request.callback) {
1657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGD("%p ~ pollOnce - returning signalled identifier %d: "
1677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        "fd=%d, events=0x%x, data=%p", this,
1687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        response.request.ident, response.request.fd,
1697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        response.events, response.request.data);
1707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outFd != NULL) *outFd = response.request.fd;
1727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outEvents != NULL) *outEvents = response.events;
1737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outData != NULL) *outData = response.request.data;
1747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return response.request.ident;
1757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
1767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
1777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (result != 0) {
1797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGD("%p ~ pollOnce - returning result %d", this, result);
1817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outFd != NULL) *outFd = 0;
1837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outEvents != NULL) *outEvents = NULL;
1847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outData != NULL) *outData = NULL;
1857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return result;
1867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
1877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        result = pollInner(timeoutMillis);
1897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollInner(int timeoutMillis) {
1937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
1957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
1978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    int result = ALOOPER_POLL_WAKE;
1988d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mResponses.clear();
1998d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mResponseIndex = 0;
2008d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS
2028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
2038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
2048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
2067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
2077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
2088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    bool acquiredLock = false;
2098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else
2108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    // Wait for wakeAndLock() waiters to run then set mPolling to true.
2118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.lock();
2128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    while (mWaiters != 0) {
2138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mResume.wait(mLock);
2148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
2158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mPolling = true;
2168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.unlock();
2178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    size_t requestedCount = mRequestedFds.size();
2198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
2208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
2218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (eventCount < 0) {
223171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        if (errno == EINTR) {
2248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            goto Done;
2257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
226171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown
227171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        LOGW("Poll failed with an unexpected error, errno=%d", errno);
2288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        result = ALOOPER_POLL_ERROR;
2298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        goto Done;
2307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (eventCount == 0) {
2337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
2347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        LOGD("%p ~ pollOnce - timeout", this);
2357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
2368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        result = ALOOPER_POLL_TIMEOUT;
2378d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        goto Done;
2387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
2417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
2427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
2438d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2448d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
2459da1810050d8825e51dabdd0262173432d49c16cJeff Brown    for (int i = 0; i < eventCount; i++) {
2469da1810050d8825e51dabdd0262173432d49c16cJeff Brown        int fd = eventItems[i].data.fd;
2479da1810050d8825e51dabdd0262173432d49c16cJeff Brown        uint32_t epollEvents = eventItems[i].events;
2489da1810050d8825e51dabdd0262173432d49c16cJeff Brown        if (fd == mWakeReadPipeFd) {
2499da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (epollEvents & EPOLLIN) {
2508d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                awoken();
2517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            } else {
2529da1810050d8825e51dabdd0262173432d49c16cJeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
2539da1810050d8825e51dabdd0262173432d49c16cJeff Brown            }
2549da1810050d8825e51dabdd0262173432d49c16cJeff Brown        } else {
2559da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (! acquiredLock) {
2569da1810050d8825e51dabdd0262173432d49c16cJeff Brown                mLock.lock();
2579da1810050d8825e51dabdd0262173432d49c16cJeff Brown                acquiredLock = true;
2589da1810050d8825e51dabdd0262173432d49c16cJeff Brown            }
2599da1810050d8825e51dabdd0262173432d49c16cJeff Brown
2609da1810050d8825e51dabdd0262173432d49c16cJeff Brown            ssize_t requestIndex = mRequests.indexOfKey(fd);
2619da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (requestIndex >= 0) {
2629da1810050d8825e51dabdd0262173432d49c16cJeff Brown                int events = 0;
2639da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
2649da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
2659da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
2669da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
2678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                pushResponse(events, mRequests.valueAt(requestIndex));
2689da1810050d8825e51dabdd0262173432d49c16cJeff Brown            } else {
2699da1810050d8825e51dabdd0262173432d49c16cJeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
2709da1810050d8825e51dabdd0262173432d49c16cJeff Brown                        "no longer registered.", epollEvents, fd);
2717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
2727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
2737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2749da1810050d8825e51dabdd0262173432d49c16cJeff Brown    if (acquiredLock) {
2759da1810050d8825e51dabdd0262173432d49c16cJeff Brown        mLock.unlock();
2769da1810050d8825e51dabdd0262173432d49c16cJeff Brown    }
2778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff BrownDone: ;
2788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else
2798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    for (size_t i = 0; i < requestedCount; i++) {
2808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
2818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
2828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        short pollEvents = requestedFd.revents;
2838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        if (pollEvents) {
2848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            if (requestedFd.fd == mWakeReadPipeFd) {
2858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLIN) {
2868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                    awoken();
2878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                } else {
2888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                    LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);
2898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                }
2908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            } else {
2918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                int events = 0;
2928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;
2938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;
2948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;
2958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;
2968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;
2978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                pushResponse(events, mRequests.itemAt(i));
2988d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            }
2998d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            if (--eventCount == 0) {
3008d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                break;
3018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            }
3028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        }
3038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
3048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
3058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff BrownDone:
3068d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    // Set mPolling to false and wake up the wakeAndLock() waiters.
3078d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.lock();
3088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mPolling = false;
3098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (mWaiters != 0) {
3108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mAwake.broadcast();
3118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
3128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.unlock();
3138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
3148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
3158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS
3168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
3178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mSampledPolls += 1;
3188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (timeoutMillis == 0) {
3198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledZeroPollCount += 1;
3208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledZeroPollLatencySum += pollEndTime - pollStartTime;
3218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) {
3228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledTimeoutPollCount += 1;
3238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime
3248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                - milliseconds_to_nanoseconds(timeoutMillis);
3258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
3268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) {
3278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout", this,
3288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount,
3298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount);
3308d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledPolls = 0;
3318d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledZeroPollCount = 0;
3328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledZeroPollLatencySum = 0;
3338d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledTimeoutPollCount = 0;
3348d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledTimeoutPollLatencySum = 0;
3358d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
3368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
3377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    for (size_t i = 0; i < mResponses.size(); i++) {
3397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        const Response& response = mResponses.itemAt(i);
3407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (response.request.callback) {
3417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
3427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this,
3437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                    response.request.fd, response.events, response.request.data);
3447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
3457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int callbackResult = response.request.callback(
3467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                    response.request.fd, response.events, response.request.data);
3477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (callbackResult == 0) {
3487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                removeFd(response.request.fd);
3497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
3507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            result = ALOOPER_POLL_CALLBACK;
3527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
3547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return result;
3557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
3567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
3587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (timeoutMillis <= 0) {
3597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        int result;
3607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        do {
3617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
3627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        } while (result == ALOOPER_POLL_CALLBACK);
3637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        return result;
3647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    } else {
3657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
3667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                + milliseconds_to_nanoseconds(timeoutMillis);
3677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        for (;;) {
3697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
3707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (result != ALOOPER_POLL_CALLBACK) {
3717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return result;
3727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
3737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
3757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (timeoutNanos <= 0) {
3767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return ALOOPER_POLL_TIMEOUT;
3777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
3787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
3807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
3827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
3837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::wake() {
3857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
3867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ wake", this);
3877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
3887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS
3908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
3918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (mPendingWakeCount++ == 0) {
3928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
3938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
3948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
3958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
396171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    ssize_t nWrite;
397171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    do {
398171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        nWrite = write(mWakeWritePipeFd, "W", 1);
399171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    } while (nWrite == -1 && errno == EINTR);
400171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown
4017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (nWrite != 1) {
4027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (errno != EAGAIN) {
4037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGW("Could not write wake signal, errno=%d", errno);
4047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
4057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
4067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
4077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::awoken() {
4098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#if DEBUG_POLL_AND_WAKE
4108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    LOGD("%p ~ awoken", this);
4118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
4128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
4138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS
4148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (mPendingWakeCount == 0) {
4158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        LOGD("%p ~ awoken: spurious!", this);
4168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    } else {
4178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledWakeCycles += 1;
4188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledWakeCountSum += mPendingWakeCount;
4198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime;
4208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mPendingWakeCount = 0;
4218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mPendingWakeTime = -1;
4228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) {
4238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle", this,
4248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                    0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles,
4258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown                    float(mSampledWakeCountSum) / mSampledWakeCycles);
4268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            mSampledWakeCycles = 0;
4278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            mSampledWakeCountSum = 0;
4288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            mSampledWakeLatencySum = 0;
4298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        }
4308d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
4318d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
4328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
4338d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    char buffer[16];
4348d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    ssize_t nRead;
4358d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    do {
4368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
4378d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
4388d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown}
4398d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
4408d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::pushResponse(int events, const Request& request) {
4418d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    Response response;
4428d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    response.events = events;
4438d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    response.request = request;
4448d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mResponses.push(response);
4458d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown}
4468d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
4477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
4487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS
4497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
4507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            events, callback, data);
4517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
4527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (! callback) {
4547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (! mAllowNonCallbacks) {
4557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
4567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
4577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
4587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (ident < 0) {
4607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Invalid attempt to set NULL callback with ident <= 0.");
4617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
4627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
4637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
4647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4658d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
4668d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    int epollEvents = 0;
4678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
4688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
4698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
4707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    { // acquire lock
4717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        AutoMutex _l(mLock);
4727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        Request request;
4747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.fd = fd;
4757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.ident = ident;
4767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.callback = callback;
4777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.data = data;
4787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        struct epoll_event eventItem;
480d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
4817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        eventItem.events = epollEvents;
4827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        eventItem.data.fd = fd;
4837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
4847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
4857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (requestIndex < 0) {
4867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
4877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (epollResult < 0) {
4887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
4897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return -1;
4907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
4917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            mRequests.add(fd, request);
4927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        } else {
4937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
4947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (epollResult < 0) {
4957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
4967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return -1;
4977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
4987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            mRequests.replaceValueAt(requestIndex, request);
4997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
5007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    } // release lock
5018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else
5028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    int pollEvents = 0;
5038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN;
5048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT;
5058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5068d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    wakeAndLock(); // acquire lock
5078d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    struct pollfd requestedFd;
5098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    requestedFd.fd = fd;
5108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    requestedFd.events = pollEvents;
5118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    Request request;
5138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.fd = fd;
5148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.ident = ident;
5158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.callback = callback;
5168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    request.data = data;
5178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    ssize_t index = getRequestIndexLocked(fd);
5188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (index < 0) {
5198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequestedFds.push(requestedFd);
5208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequests.push(request);
5218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    } else {
5228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequestedFds.replaceAt(requestedFd, size_t(index));
5238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequests.replaceAt(request, size_t(index));
5248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
5258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.unlock(); // release lock
5278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
5287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return 1;
5297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
5307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
5317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::removeFd(int fd) {
5327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS
5337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ removeFd - fd=%d", this, fd);
5347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
5357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
5368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL
5377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    { // acquire lock
5387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        AutoMutex _l(mLock);
5397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
5407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (requestIndex < 0) {
5417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return 0;
5427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
5437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
5447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
5457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (epollResult < 0) {
5467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
5477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
5487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
5497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
5507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mRequests.removeItemsAt(requestIndex);
5518d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    } // release lock
5527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return 1;
5538d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else
5548d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    wakeAndLock(); // acquire lock
5558d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5568d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    ssize_t index = getRequestIndexLocked(fd);
5578d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (index >= 0) {
5588d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequestedFds.removeAt(size_t(index));
5598d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mRequests.removeAt(size_t(index));
5608d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
5618d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5628d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.unlock(); // release lock
5638d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    return index >= 0;
5648d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
5657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
5667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
5678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifndef LOOPER_USES_EPOLL
5688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownssize_t Looper::getRequestIndexLocked(int fd) {
5698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    size_t requestCount = mRequestedFds.size();
5708d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5718d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    for (size_t i = 0; i < requestCount; i++) {
5728d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        if (mRequestedFds.itemAt(i).fd == fd) {
5738d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown            return i;
5748d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        }
5758d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
5768d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    return -1;
5788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown}
5798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::wakeAndLock() {
5818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mLock.lock();
5828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mWaiters += 1;
5848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    while (mPolling) {
5858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        wake();
5868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mAwake.wait(mLock);
5878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
5888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    mWaiters -= 1;
5908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    if (mWaiters == 0) {
5918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown        mResume.signal();
5928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown    }
5938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown}
5948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif
5958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown
5967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} // namespace android
597