Looper.cpp revision 54e1cdacd2b132997fdca5e5b90e45855c7a2a95
159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown//
259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// Copyright 2010 The Android Open Source Project
359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown//
459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// A looper implementation based on epoll().
559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown//
659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#define LOG_TAG "Looper"
759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown//#define LOG_NDEBUG 0
959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
1059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// Debugs poll and wake interactions.
1159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#define DEBUG_POLL_AND_WAKE 0
1259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
1359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// Debugs callback registration and invocation.
1459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#define DEBUG_CALLBACKS 0
1559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
1659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#include <cutils/log.h>
1759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#include <utils/Looper.h>
1859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#include <utils/Timers.h>
1959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#include <unistd.h>
2159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#include <fcntl.h>
2259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownnamespace android {
2559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
2759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// Hint for number of file descriptors to be associated with the epoll instance.
2859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownstatic const int EPOLL_SIZE_HINT = 8;
2959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
3059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown// Maximum number of file descriptors for which to retrieve poll events each iteration.
3159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownstatic const int EPOLL_MAX_EVENTS = 16;
3254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
3359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
3461a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
3561a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownstatic pthread_key_t gTLSKey = 0;
3661a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown
3759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff BrownLooper::Looper(bool allowNonCallbacks) :
3859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mAllowNonCallbacks(allowNonCallbacks),
3959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mResponseIndex(0) {
4059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int wakeFds[2];
4159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int result = pipe(wakeFds);
4259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
4359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
4459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mWakeReadPipeFd = wakeFds[0];
4559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mWakeWritePipeFd = wakeFds[1];
4659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
4759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
4859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
4959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
5059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
5159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
5259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
5359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
5459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
5554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
5654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    // Allocate the epoll instance and register the wake pipe.
5754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
5854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
5954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
6059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    struct epoll_event eventItem;
6161a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
6259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    eventItem.events = EPOLLIN;
6359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    eventItem.data.fd = mWakeReadPipeFd;
6459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
6559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
6659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
6754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#else
6854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    // Add the wake pipe to the head of the request list with a null callback.
6954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    struct pollfd requestedFd;
7054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    requestedFd.fd = mWakeReadPipeFd;
7154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    requestedFd.events = POLLIN;
7254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mRequestedFds.push(requestedFd);
7354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
7454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    Request request;
7554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.fd = mWakeReadPipeFd;
7654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.callback = NULL;
7754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.ident = 0;
7854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.data = NULL;
7954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mRequests.push(request);
8054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
8154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mPolling = false;
8254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mWaiters = 0;
8354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
8454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
8554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_STATISTICS
8654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mPendingWakeTime = -1;
8754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mPendingWakeCount = 0;
8854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledWakeCycles = 0;
8954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledWakeCountSum = 0;
9054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledWakeLatencySum = 0;
9154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
9254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledPolls = 0;
9354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledZeroPollCount = 0;
9454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledZeroPollLatencySum = 0;
9554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledTimeoutPollCount = 0;
9654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledTimeoutPollLatencySum = 0;
9754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
9859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
9959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
10059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff BrownLooper::~Looper() {
10159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mWakeReadPipeFd);
10259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mWakeWritePipeFd);
10354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
10459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mEpollFd);
10554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
10659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
10759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
10861a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownvoid Looper::initTLSKey() {
10961a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    int result = pthread_key_create(& gTLSKey, threadDestructor);
11061a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
11161a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown}
11261a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown
11359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::threadDestructor(void *st) {
11459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    Looper* const self = static_cast<Looper*>(st);
11559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (self != NULL) {
11659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        self->decStrong((void*)threadDestructor);
11759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
11859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
11959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
12059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::setForThread(const sp<Looper>& looper) {
12159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
12259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
12359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper != NULL) {
12459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        looper->incStrong((void*)threadDestructor);
12559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
12659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
12761a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    pthread_setspecific(gTLSKey, looper.get());
12859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
12959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (old != NULL) {
13059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        old->decStrong((void*)threadDestructor);
13159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
13259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
13359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
13459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownsp<Looper> Looper::getForThread() {
13561a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    int result = pthread_once(& gTLSOnce, initTLSKey);
13661a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
13759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
13861a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    return (Looper*)pthread_getspecific(gTLSKey);
13959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
14059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
14159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownsp<Looper> Looper::prepare(int opts) {
14259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
14359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    sp<Looper> looper = Looper::getForThread();
14459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper == NULL) {
14559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        looper = new Looper(allowNonCallbacks);
14659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        Looper::setForThread(looper);
14759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
14859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
14959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        LOGW("Looper already prepared for this thread with a different value for the "
15059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
15159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
15259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return looper;
15359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
15459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
15559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownbool Looper::getAllowNonCallbacks() const {
15659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return mAllowNonCallbacks;
15759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
15859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
15959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
16059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int result = 0;
16159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    for (;;) {
16259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        while (mResponseIndex < mResponses.size()) {
16359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            const Response& response = mResponses.itemAt(mResponseIndex++);
16459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (! response.request.callback) {
16559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
16659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGD("%p ~ pollOnce - returning signalled identifier %d: "
16759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        "fd=%d, events=0x%x, data=%p", this,
16859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        response.request.ident, response.request.fd,
16959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        response.events, response.request.data);
17059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
17159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outFd != NULL) *outFd = response.request.fd;
17259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outEvents != NULL) *outEvents = response.events;
17359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outData != NULL) *outData = response.request.data;
17459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return response.request.ident;
17559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
17659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
17759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
17859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (result != 0) {
17959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
18059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGD("%p ~ pollOnce - returning result %d", this, result);
18159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
18259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outFd != NULL) *outFd = 0;
18359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outEvents != NULL) *outEvents = NULL;
18459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outData != NULL) *outData = NULL;
18559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return result;
18659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
18759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
18859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        result = pollInner(timeoutMillis);
18959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
19059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
19159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
19259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollInner(int timeoutMillis) {
19359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
19459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
19559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
19654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
19754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    int result = ALOOPER_POLL_WAKE;
19854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mResponses.clear();
19954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mResponseIndex = 0;
20054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
20154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_STATISTICS
20254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
20354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
20454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
20554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
20659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
20759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
20854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    bool acquiredLock = false;
20954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#else
21054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    // Wait for wakeAndLock() waiters to run then set mPolling to true.
21154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.lock();
21254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    while (mWaiters != 0) {
21354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mResume.wait(mLock);
21454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
21554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mPolling = true;
21654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.unlock();
21754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
21854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    size_t requestedCount = mRequestedFds.size();
21954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
22054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
22154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
22259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (eventCount < 0) {
223f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        if (errno == EINTR) {
22454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            goto Done;
22559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
226f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown
227f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        LOGW("Poll failed with an unexpected error, errno=%d", errno);
22854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        result = ALOOPER_POLL_ERROR;
22954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        goto Done;
23059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
23159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
23259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (eventCount == 0) {
23359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
23459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        LOGD("%p ~ pollOnce - timeout", this);
23559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
23654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        result = ALOOPER_POLL_TIMEOUT;
23754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        goto Done;
23859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
23959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
24059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
24159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
24259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
24354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
24454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
245ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    for (int i = 0; i < eventCount; i++) {
246ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        int fd = eventItems[i].data.fd;
247ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        uint32_t epollEvents = eventItems[i].events;
248ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        if (fd == mWakeReadPipeFd) {
249ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (epollEvents & EPOLLIN) {
25054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                awoken();
25159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            } else {
252ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
253ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            }
254ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        } else {
255ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (! acquiredLock) {
256ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                mLock.lock();
257ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                acquiredLock = true;
258ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            }
259ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown
260ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            ssize_t requestIndex = mRequests.indexOfKey(fd);
261ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (requestIndex >= 0) {
262ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                int events = 0;
263ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
264ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
265ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
266ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
26754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                pushResponse(events, mRequests.valueAt(requestIndex));
268ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            } else {
269ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
270ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                        "no longer registered.", epollEvents, fd);
27159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
27259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
27359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
274ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    if (acquiredLock) {
275ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        mLock.unlock();
276ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    }
27754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff BrownDone: ;
27854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#else
27954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    for (size_t i = 0; i < requestedCount; i++) {
28054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
28154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
28254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        short pollEvents = requestedFd.revents;
28354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        if (pollEvents) {
28454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            if (requestedFd.fd == mWakeReadPipeFd) {
28554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLIN) {
28654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                    awoken();
28754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                } else {
28854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                    LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);
28954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                }
29054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            } else {
29154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                int events = 0;
29254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;
29354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;
29454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;
29554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;
29654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;
29754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                pushResponse(events, mRequests.itemAt(i));
29854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            }
29954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            if (--eventCount == 0) {
30054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                break;
30154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            }
30254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        }
30354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
30454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
30554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff BrownDone:
30654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    // Set mPolling to false and wake up the wakeAndLock() waiters.
30754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.lock();
30854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mPolling = false;
30954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (mWaiters != 0) {
31054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mAwake.broadcast();
31154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
31254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.unlock();
31354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
31454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
31554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_STATISTICS
31654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
31754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mSampledPolls += 1;
31854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (timeoutMillis == 0) {
31954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledZeroPollCount += 1;
32054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledZeroPollLatencySum += pollEndTime - pollStartTime;
32154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) {
32254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledTimeoutPollCount += 1;
32354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime
32454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                - milliseconds_to_nanoseconds(timeoutMillis);
32554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
32654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) {
32754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout", this,
32854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount,
32954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount);
33054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledPolls = 0;
33154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledZeroPollCount = 0;
33254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledZeroPollLatencySum = 0;
33354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledTimeoutPollCount = 0;
33454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledTimeoutPollLatencySum = 0;
33554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
33654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
33759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
33859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    for (size_t i = 0; i < mResponses.size(); i++) {
33959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        const Response& response = mResponses.itemAt(i);
34059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (response.request.callback) {
34159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
34259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this,
34359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                    response.request.fd, response.events, response.request.data);
34459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
34559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int callbackResult = response.request.callback(
34659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                    response.request.fd, response.events, response.request.data);
34759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (callbackResult == 0) {
34859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                removeFd(response.request.fd);
34959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
35059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
35159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            result = ALOOPER_POLL_CALLBACK;
35259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
35359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
35459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return result;
35559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
35659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
35759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
35859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (timeoutMillis <= 0) {
35959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        int result;
36059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        do {
36159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
36259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        } while (result == ALOOPER_POLL_CALLBACK);
36359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        return result;
36459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    } else {
36559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
36659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                + milliseconds_to_nanoseconds(timeoutMillis);
36759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
36859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        for (;;) {
36959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
37059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (result != ALOOPER_POLL_CALLBACK) {
37159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return result;
37259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
37359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
37459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
37559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (timeoutNanos <= 0) {
37659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return ALOOPER_POLL_TIMEOUT;
37759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
37859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
37959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
38059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
38159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
38259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
38359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
38459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::wake() {
38559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
38659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ wake", this);
38759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
38859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
38954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_STATISTICS
39054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
39154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (mPendingWakeCount++ == 0) {
39254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
39354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
39454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
39554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
396f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    ssize_t nWrite;
397f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    do {
398f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        nWrite = write(mWakeWritePipeFd, "W", 1);
399f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    } while (nWrite == -1 && errno == EINTR);
400f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown
40159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (nWrite != 1) {
40259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (errno != EAGAIN) {
40359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGW("Could not write wake signal, errno=%d", errno);
40459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
40559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
40659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
40759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
40854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brownvoid Looper::awoken() {
40954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#if DEBUG_POLL_AND_WAKE
41054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    LOGD("%p ~ awoken", this);
41154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
41254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
41354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_STATISTICS
41454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (mPendingWakeCount == 0) {
41554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        LOGD("%p ~ awoken: spurious!", this);
41654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    } else {
41754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledWakeCycles += 1;
41854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledWakeCountSum += mPendingWakeCount;
41954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime;
42054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mPendingWakeCount = 0;
42154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mPendingWakeTime = -1;
42254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) {
42354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle", this,
42454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                    0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles,
42554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown                    float(mSampledWakeCountSum) / mSampledWakeCycles);
42654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            mSampledWakeCycles = 0;
42754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            mSampledWakeCountSum = 0;
42854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            mSampledWakeLatencySum = 0;
42954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        }
43054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
43154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
43254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
43354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    char buffer[16];
43454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    ssize_t nRead;
43554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    do {
43654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
43754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
43854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown}
43954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
44054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brownvoid Looper::pushResponse(int events, const Request& request) {
44154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    Response response;
44254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    response.events = events;
44354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    response.request = request;
44454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mResponses.push(response);
44554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown}
44654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
44759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
44859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_CALLBACKS
44959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
45059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            events, callback, data);
45159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
45259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
45359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (! callback) {
45459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (! mAllowNonCallbacks) {
45559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
45659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
45759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
45859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
45959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (ident < 0) {
46059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Invalid attempt to set NULL callback with ident <= 0.");
46159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
46259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
46359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
46459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
46554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
46654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    int epollEvents = 0;
46754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
46854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
46954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
47059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    { // acquire lock
47159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        AutoMutex _l(mLock);
47259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
47359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        Request request;
47459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.fd = fd;
47559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.ident = ident;
47659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.callback = callback;
47759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.data = data;
47859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
47959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        struct epoll_event eventItem;
48061a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
48159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        eventItem.events = epollEvents;
48259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        eventItem.data.fd = fd;
48359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
48459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
48559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (requestIndex < 0) {
48659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
48759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (epollResult < 0) {
48859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
48959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return -1;
49059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
49159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            mRequests.add(fd, request);
49259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        } else {
49359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
49459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (epollResult < 0) {
49559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
49659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return -1;
49759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
49859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            mRequests.replaceValueAt(requestIndex, request);
49959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
50059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    } // release lock
50154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#else
50254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    int pollEvents = 0;
50354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN;
50454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT;
50554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
50654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    wakeAndLock(); // acquire lock
50754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
50854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    struct pollfd requestedFd;
50954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    requestedFd.fd = fd;
51054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    requestedFd.events = pollEvents;
51154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
51254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    Request request;
51354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.fd = fd;
51454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.ident = ident;
51554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.callback = callback;
51654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    request.data = data;
51754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    ssize_t index = getRequestIndexLocked(fd);
51854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (index < 0) {
51954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequestedFds.push(requestedFd);
52054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequests.push(request);
52154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    } else {
52254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequestedFds.replaceAt(requestedFd, size_t(index));
52354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequests.replaceAt(request, size_t(index));
52454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
52554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
52654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.unlock(); // release lock
52754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
52859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return 1;
52959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
53059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
53159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::removeFd(int fd) {
53259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_CALLBACKS
53359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ removeFd - fd=%d", this, fd);
53459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
53559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
53654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifdef LOOPER_USES_EPOLL
53759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    { // acquire lock
53859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        AutoMutex _l(mLock);
53959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
54059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (requestIndex < 0) {
54159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return 0;
54259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
54359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
54459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
54559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (epollResult < 0) {
54659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
54759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
54859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
54959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
55059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mRequests.removeItemsAt(requestIndex);
55154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    } // release lock
55259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return 1;
55354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#else
55454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    wakeAndLock(); // acquire lock
55554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
55654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    ssize_t index = getRequestIndexLocked(fd);
55754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (index >= 0) {
55854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequestedFds.removeAt(size_t(index));
55954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mRequests.removeAt(size_t(index));
56054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
56154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
56254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.unlock(); // release lock
56354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    return index >= 0;
56454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
56559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
56659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
56754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#ifndef LOOPER_USES_EPOLL
56854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brownssize_t Looper::getRequestIndexLocked(int fd) {
56954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    size_t requestCount = mRequestedFds.size();
57054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
57154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    for (size_t i = 0; i < requestCount; i++) {
57254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        if (mRequestedFds.itemAt(i).fd == fd) {
57354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown            return i;
57454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        }
57554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
57654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
57754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    return -1;
57854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown}
57954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
58054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brownvoid Looper::wakeAndLock() {
58154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mLock.lock();
58254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
58354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mWaiters += 1;
58454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    while (mPolling) {
58554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        wake();
58654e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mAwake.wait(mLock);
58754e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
58854e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
58954e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    mWaiters -= 1;
59054e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    if (mWaiters == 0) {
59154e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown        mResume.signal();
59254e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown    }
59354e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown}
59454e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown#endif
59554e1cdacd2b132997fdca5e5b90e45855c7a2a95Jeff Brown
59659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown} // namespace android
597