Looper.cpp revision d18051870e8e2a5f55237a2c11fde75f46082639
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#include <sys/epoll.h>
237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownnamespace android {
267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
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;
327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
33d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
34d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_key_t gTLSKey = 0;
35d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown
367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::Looper(bool allowNonCallbacks) :
377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mAllowNonCallbacks(allowNonCallbacks),
387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mResponseIndex(0) {
397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int wakeFds[2];
437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int result = pipe(wakeFds);
447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mWakeReadPipeFd = wakeFds[0];
477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mWakeWritePipeFd = wakeFds[1];
487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    struct epoll_event eventItem;
58d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    eventItem.events = EPOLLIN;
607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    eventItem.data.fd = mWakeReadPipeFd;
617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            errno);
647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::~Looper() {
677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mWakeReadPipeFd);
687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mWakeWritePipeFd);
697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    close(mEpollFd);
707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
72d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownvoid Looper::initTLSKey() {
73d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    int result = pthread_key_create(& gTLSKey, threadDestructor);
74d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
75d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown}
76d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown
777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::threadDestructor(void *st) {
787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    Looper* const self = static_cast<Looper*>(st);
797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (self != NULL) {
807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        self->decStrong((void*)threadDestructor);
817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::setForThread(const sp<Looper>& looper) {
857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper != NULL) {
887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        looper->incStrong((void*)threadDestructor);
897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
91d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    pthread_setspecific(gTLSKey, looper.get());
927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (old != NULL) {
947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        old->decStrong((void*)threadDestructor);
957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::getForThread() {
99d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    int result = pthread_once(& gTLSOnce, initTLSKey);
100d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
1017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
102d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown    return (Looper*)pthread_getspecific(gTLSKey);
1037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::prepare(int opts) {
1067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
1077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    sp<Looper> looper = Looper::getForThread();
1087901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper == NULL) {
1097901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        looper = new Looper(allowNonCallbacks);
1107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        Looper::setForThread(looper);
1117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
1137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        LOGW("Looper already prepared for this thread with a different value for the "
1147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
1157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return looper;
1177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownbool Looper::getAllowNonCallbacks() const {
1207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return mAllowNonCallbacks;
1217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
1247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int result = 0;
1257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    for (;;) {
1267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        while (mResponseIndex < mResponses.size()) {
1277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            const Response& response = mResponses.itemAt(mResponseIndex++);
1287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (! response.request.callback) {
1297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGD("%p ~ pollOnce - returning signalled identifier %d: "
1317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        "fd=%d, events=0x%x, data=%p", this,
1327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        response.request.ident, response.request.fd,
1337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                        response.events, response.request.data);
1347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outFd != NULL) *outFd = response.request.fd;
1367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outEvents != NULL) *outEvents = response.events;
1377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                if (outData != NULL) *outData = response.request.data;
1387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return response.request.ident;
1397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
1407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
1417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (result != 0) {
1437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGD("%p ~ pollOnce - returning result %d", this, result);
1457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outFd != NULL) *outFd = 0;
1477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outEvents != NULL) *outEvents = NULL;
1487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (outData != NULL) *outData = NULL;
1497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return result;
1507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
1517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        result = pollInner(timeoutMillis);
1537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
1557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollInner(int timeoutMillis) {
1577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
1597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
1617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
1627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (eventCount < 0) {
163171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        if (errno == EINTR) {
164171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown            return ALOOPER_POLL_WAKE;
1657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
166171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown
167171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        LOGW("Poll failed with an unexpected error, errno=%d", errno);
1687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        return ALOOPER_POLL_ERROR;
1697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (eventCount == 0) {
1727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        LOGD("%p ~ pollOnce - timeout", this);
1747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        return ALOOPER_POLL_TIMEOUT;
1767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
1777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int result = ALOOPER_POLL_WAKE;
1797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mResponses.clear();
1807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    mResponseIndex = 0;
1817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
1827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
1847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1859da1810050d8825e51dabdd0262173432d49c16cJeff Brown    bool acquiredLock = false;
1869da1810050d8825e51dabdd0262173432d49c16cJeff Brown    for (int i = 0; i < eventCount; i++) {
1879da1810050d8825e51dabdd0262173432d49c16cJeff Brown        int fd = eventItems[i].data.fd;
1889da1810050d8825e51dabdd0262173432d49c16cJeff Brown        uint32_t epollEvents = eventItems[i].events;
1899da1810050d8825e51dabdd0262173432d49c16cJeff Brown        if (fd == mWakeReadPipeFd) {
1909da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (epollEvents & EPOLLIN) {
1917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
1929da1810050d8825e51dabdd0262173432d49c16cJeff Brown                LOGD("%p ~ pollOnce - awoken", this);
1937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
1949da1810050d8825e51dabdd0262173432d49c16cJeff Brown                char buffer[16];
1959da1810050d8825e51dabdd0262173432d49c16cJeff Brown                ssize_t nRead;
1969da1810050d8825e51dabdd0262173432d49c16cJeff Brown                do {
1979da1810050d8825e51dabdd0262173432d49c16cJeff Brown                    nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
1989da1810050d8825e51dabdd0262173432d49c16cJeff Brown                } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
1997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            } else {
2009da1810050d8825e51dabdd0262173432d49c16cJeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
2019da1810050d8825e51dabdd0262173432d49c16cJeff Brown            }
2029da1810050d8825e51dabdd0262173432d49c16cJeff Brown        } else {
2039da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (! acquiredLock) {
2049da1810050d8825e51dabdd0262173432d49c16cJeff Brown                mLock.lock();
2059da1810050d8825e51dabdd0262173432d49c16cJeff Brown                acquiredLock = true;
2069da1810050d8825e51dabdd0262173432d49c16cJeff Brown            }
2079da1810050d8825e51dabdd0262173432d49c16cJeff Brown
2089da1810050d8825e51dabdd0262173432d49c16cJeff Brown            ssize_t requestIndex = mRequests.indexOfKey(fd);
2099da1810050d8825e51dabdd0262173432d49c16cJeff Brown            if (requestIndex >= 0) {
2109da1810050d8825e51dabdd0262173432d49c16cJeff Brown                int events = 0;
2119da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
2129da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
2139da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
2149da1810050d8825e51dabdd0262173432d49c16cJeff Brown                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
2159da1810050d8825e51dabdd0262173432d49c16cJeff Brown
2169da1810050d8825e51dabdd0262173432d49c16cJeff Brown                Response response;
2179da1810050d8825e51dabdd0262173432d49c16cJeff Brown                response.events = events;
2189da1810050d8825e51dabdd0262173432d49c16cJeff Brown                response.request = mRequests.valueAt(requestIndex);
2199da1810050d8825e51dabdd0262173432d49c16cJeff Brown                mResponses.push(response);
2209da1810050d8825e51dabdd0262173432d49c16cJeff Brown            } else {
2219da1810050d8825e51dabdd0262173432d49c16cJeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
2229da1810050d8825e51dabdd0262173432d49c16cJeff Brown                        "no longer registered.", epollEvents, fd);
2237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
2247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
2257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2269da1810050d8825e51dabdd0262173432d49c16cJeff Brown    if (acquiredLock) {
2279da1810050d8825e51dabdd0262173432d49c16cJeff Brown        mLock.unlock();
2289da1810050d8825e51dabdd0262173432d49c16cJeff Brown    }
2297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    for (size_t i = 0; i < mResponses.size(); i++) {
2317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        const Response& response = mResponses.itemAt(i);
2327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (response.request.callback) {
2337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
2347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this,
2357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                    response.request.fd, response.events, response.request.data);
2367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
2377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int callbackResult = response.request.callback(
2387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                    response.request.fd, response.events, response.request.data);
2397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (callbackResult == 0) {
2407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                removeFd(response.request.fd);
2417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
2427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            result = ALOOPER_POLL_CALLBACK;
2447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
2457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return result;
2477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
2487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
2507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (timeoutMillis <= 0) {
2517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        int result;
2527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        do {
2537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
2547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        } while (result == ALOOPER_POLL_CALLBACK);
2557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        return result;
2567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    } else {
2577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
2587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                + milliseconds_to_nanoseconds(timeoutMillis);
2597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        for (;;) {
2617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
2627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (result != ALOOPER_POLL_CALLBACK) {
2637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return result;
2647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
2657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
2677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (timeoutNanos <= 0) {
2687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return ALOOPER_POLL_TIMEOUT;
2697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
2707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
2727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
2737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
2757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::wake() {
2777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE
2787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ wake", this);
2797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
2807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
281171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    ssize_t nWrite;
282171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    do {
283171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown        nWrite = write(mWakeWritePipeFd, "W", 1);
284171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown    } while (nWrite == -1 && errno == EINTR);
285171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown
2867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (nWrite != 1) {
2877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (errno != EAGAIN) {
2887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGW("Could not write wake signal, errno=%d", errno);
2897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
2907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
2917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
2927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
2947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS
2957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
2967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            events, callback, data);
2977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
2987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
2997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    int epollEvents = 0;
3007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
3017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
3027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (events & ALOOPER_EVENT_ERROR) epollEvents |= EPOLLERR;
3037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (events & ALOOPER_EVENT_HANGUP) epollEvents |= EPOLLHUP;
3047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (epollEvents == 0) {
3067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        LOGE("Invalid attempt to set a callback with no selected poll events.");
3077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        return -1;
3087901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
3097901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    if (! callback) {
3117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (! mAllowNonCallbacks) {
3127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
3137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
3147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (ident < 0) {
3177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Invalid attempt to set NULL callback with ident <= 0.");
3187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
3197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    }
3217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    { // acquire lock
3237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        AutoMutex _l(mLock);
3247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        Request request;
3267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.fd = fd;
3277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.ident = ident;
3287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.callback = callback;
3297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        request.data = data;
3307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        struct epoll_event eventItem;
332d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
3337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        eventItem.events = epollEvents;
3347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        eventItem.data.fd = fd;
3357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
3377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (requestIndex < 0) {
3387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
3397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (epollResult < 0) {
3407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
3417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return -1;
3427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
3437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            mRequests.add(fd, request);
3447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        } else {
3457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
3467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            if (epollResult < 0) {
3477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
3487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown                return -1;
3497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            }
3507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            mRequests.replaceValueAt(requestIndex, request);
3517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    } // release lock
3537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return 1;
3547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
3557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::removeFd(int fd) {
3577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS
3587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    LOGD("%p ~ removeFd - fd=%d", this, fd);
3597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif
3607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    { // acquire lock
3627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        AutoMutex _l(mLock);
3637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
3647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (requestIndex < 0) {
3657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return 0;
3667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
3697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        if (epollResult < 0) {
3707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
3717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown            return -1;
3727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        }
3737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown        mRequests.removeItemsAt(requestIndex);
3757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    } // request lock
3767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown    return 1;
3777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown}
3787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown
3797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} // namespace android
380