Looper.cpp revision 61a25b249066baed0fdab0411f44a2c6b7292766
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#include <sys/epoll.h>
2359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
2559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownnamespace android {
2659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
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;
3259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
3361a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
3461a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownstatic pthread_key_t gTLSKey = 0;
3561a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown
3659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff BrownLooper::Looper(bool allowNonCallbacks) :
3759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mAllowNonCallbacks(allowNonCallbacks),
3859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mResponseIndex(0) {
3959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
4059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
4159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
4259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int wakeFds[2];
4359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int result = pipe(wakeFds);
4459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
4559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
4659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mWakeReadPipeFd = wakeFds[0];
4759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mWakeWritePipeFd = wakeFds[1];
4859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
4959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
5059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
5159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
5259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
5359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
5459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
5559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
5659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
5759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    struct epoll_event eventItem;
5861a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
5959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    eventItem.events = EPOLLIN;
6059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    eventItem.data.fd = mWakeReadPipeFd;
6159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
6259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
6359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            errno);
6459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
6559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
6659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff BrownLooper::~Looper() {
6759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mWakeReadPipeFd);
6859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mWakeWritePipeFd);
6959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    close(mEpollFd);
7059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
7159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
7261a25b249066baed0fdab0411f44a2c6b7292766Jeff Brownvoid Looper::initTLSKey() {
7361a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    int result = pthread_key_create(& gTLSKey, threadDestructor);
7461a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
7561a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown}
7661a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown
7759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::threadDestructor(void *st) {
7859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    Looper* const self = static_cast<Looper*>(st);
7959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (self != NULL) {
8059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        self->decStrong((void*)threadDestructor);
8159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
8259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
8359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
8459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::setForThread(const sp<Looper>& looper) {
8559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
8659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
8759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper != NULL) {
8859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        looper->incStrong((void*)threadDestructor);
8959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
9059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
9161a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    pthread_setspecific(gTLSKey, looper.get());
9259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
9359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (old != NULL) {
9459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        old->decStrong((void*)threadDestructor);
9559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
9659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
9759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
9859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownsp<Looper> Looper::getForThread() {
9961a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    int result = pthread_once(& gTLSOnce, initTLSKey);
10061a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
10159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
10261a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown    return (Looper*)pthread_getspecific(gTLSKey);
10359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
10459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
10559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownsp<Looper> Looper::prepare(int opts) {
10659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
10759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    sp<Looper> looper = Looper::getForThread();
10859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper == NULL) {
10959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        looper = new Looper(allowNonCallbacks);
11059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        Looper::setForThread(looper);
11159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
11259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
11359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        LOGW("Looper already prepared for this thread with a different value for the "
11459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
11559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
11659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return looper;
11759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
11859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
11959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownbool Looper::getAllowNonCallbacks() const {
12059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return mAllowNonCallbacks;
12159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
12259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
12359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
12459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int result = 0;
12559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    for (;;) {
12659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        while (mResponseIndex < mResponses.size()) {
12759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            const Response& response = mResponses.itemAt(mResponseIndex++);
12859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (! response.request.callback) {
12959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
13059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGD("%p ~ pollOnce - returning signalled identifier %d: "
13159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        "fd=%d, events=0x%x, data=%p", this,
13259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        response.request.ident, response.request.fd,
13359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                        response.events, response.request.data);
13459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
13559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outFd != NULL) *outFd = response.request.fd;
13659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outEvents != NULL) *outEvents = response.events;
13759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                if (outData != NULL) *outData = response.request.data;
13859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return response.request.ident;
13959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
14059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
14159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
14259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (result != 0) {
14359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
14459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGD("%p ~ pollOnce - returning result %d", this, result);
14559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
14659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outFd != NULL) *outFd = 0;
14759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outEvents != NULL) *outEvents = NULL;
14859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (outData != NULL) *outData = NULL;
14959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return result;
15059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
15159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
15259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        result = pollInner(timeoutMillis);
15359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
15459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
15559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
15659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollInner(int timeoutMillis) {
15759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
15859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
15959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
16059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
16159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
16259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (eventCount < 0) {
163f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        if (errno == EINTR) {
164f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown            return ALOOPER_POLL_WAKE;
16559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
166f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown
167f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        LOGW("Poll failed with an unexpected error, errno=%d", errno);
16859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        return ALOOPER_POLL_ERROR;
16959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
17059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
17159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (eventCount == 0) {
17259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
17359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        LOGD("%p ~ pollOnce - timeout", this);
17459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
17559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        return ALOOPER_POLL_TIMEOUT;
17659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
17759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
17859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int result = ALOOPER_POLL_WAKE;
17959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mResponses.clear();
18059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    mResponseIndex = 0;
18159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
18259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
18359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
18459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
185ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    bool acquiredLock = false;
186ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    for (int i = 0; i < eventCount; i++) {
187ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        int fd = eventItems[i].data.fd;
188ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        uint32_t epollEvents = eventItems[i].events;
189ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        if (fd == mWakeReadPipeFd) {
190ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (epollEvents & EPOLLIN) {
19159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
192ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                LOGD("%p ~ pollOnce - awoken", this);
19359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
194ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                char buffer[16];
195ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                ssize_t nRead;
196ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                do {
197ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                    nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
198ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
19959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            } else {
200ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
201ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            }
202ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        } else {
203ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (! acquiredLock) {
204ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                mLock.lock();
205ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                acquiredLock = true;
206ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            }
207ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown
208ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            ssize_t requestIndex = mRequests.indexOfKey(fd);
209ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            if (requestIndex >= 0) {
210ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                int events = 0;
211ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
212ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
213ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
214ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
215ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown
216ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                Response response;
217ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                response.events = events;
218ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                response.request = mRequests.valueAt(requestIndex);
219ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                mResponses.push(response);
220ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown            } else {
221ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
222ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown                        "no longer registered.", epollEvents, fd);
22359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
22459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
22559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
226ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    if (acquiredLock) {
227ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown        mLock.unlock();
228ed242de3f5b709e9e0925513ab976886a04358c0Jeff Brown    }
22959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
23059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    for (size_t i = 0; i < mResponses.size(); i++) {
23159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        const Response& response = mResponses.itemAt(i);
23259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (response.request.callback) {
23359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
23459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this,
23559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                    response.request.fd, response.events, response.request.data);
23659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
23759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int callbackResult = response.request.callback(
23859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                    response.request.fd, response.events, response.request.data);
23959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (callbackResult == 0) {
24059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                removeFd(response.request.fd);
24159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
24259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
24359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            result = ALOOPER_POLL_CALLBACK;
24459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
24559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
24659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return result;
24759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
24859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
24959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
25059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (timeoutMillis <= 0) {
25159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        int result;
25259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        do {
25359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
25459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        } while (result == ALOOPER_POLL_CALLBACK);
25559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        return result;
25659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    } else {
25759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
25859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                + milliseconds_to_nanoseconds(timeoutMillis);
25959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
26059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        for (;;) {
26159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
26259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (result != ALOOPER_POLL_CALLBACK) {
26359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return result;
26459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
26559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
26659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
26759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (timeoutNanos <= 0) {
26859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return ALOOPER_POLL_TIMEOUT;
26959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
27059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
27159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
27259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
27359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
27459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
27559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
27659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownvoid Looper::wake() {
27759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_POLL_AND_WAKE
27859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ wake", this);
27959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
28059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
281f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    ssize_t nWrite;
282f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    do {
283f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown        nWrite = write(mWakeWritePipeFd, "W", 1);
284f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown    } while (nWrite == -1 && errno == EINTR);
285f67f29903680e7a33af020dbeb80697ad619b26eJeff Brown
28659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (nWrite != 1) {
28759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (errno != EAGAIN) {
28859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGW("Could not write wake signal, errno=%d", errno);
28959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
29059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
29159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
29259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
29359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
29459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_CALLBACKS
29559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
29659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            events, callback, data);
29759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
29859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
29959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    int epollEvents = 0;
30059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
30159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
30259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (events & ALOOPER_EVENT_ERROR) epollEvents |= EPOLLERR;
30359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (events & ALOOPER_EVENT_HANGUP) epollEvents |= EPOLLHUP;
30459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
30559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (epollEvents == 0) {
30659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        LOGE("Invalid attempt to set a callback with no selected poll events.");
30759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        return -1;
30859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
30959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
31059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    if (! callback) {
31159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (! mAllowNonCallbacks) {
31259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
31359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
31459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
31559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
31659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (ident < 0) {
31759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Invalid attempt to set NULL callback with ident <= 0.");
31859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
31959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
32059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    }
32159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
32259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    { // acquire lock
32359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        AutoMutex _l(mLock);
32459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
32559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        Request request;
32659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.fd = fd;
32759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.ident = ident;
32859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.callback = callback;
32959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        request.data = data;
33059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
33159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        struct epoll_event eventItem;
33261a25b249066baed0fdab0411f44a2c6b7292766Jeff Brown        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
33359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        eventItem.events = epollEvents;
33459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        eventItem.data.fd = fd;
33559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
33659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
33759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (requestIndex < 0) {
33859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
33959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (epollResult < 0) {
34059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
34159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return -1;
34259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
34359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            mRequests.add(fd, request);
34459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        } else {
34559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
34659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            if (epollResult < 0) {
34759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
34859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown                return -1;
34959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            }
35059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            mRequests.replaceValueAt(requestIndex, request);
35159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
35259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    } // release lock
35359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return 1;
35459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
35559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
35659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brownint Looper::removeFd(int fd) {
35759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#if DEBUG_CALLBACKS
35859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    LOGD("%p ~ removeFd - fd=%d", this, fd);
35959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown#endif
36059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
36159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    { // acquire lock
36259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        AutoMutex _l(mLock);
36359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        ssize_t requestIndex = mRequests.indexOfKey(fd);
36459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (requestIndex < 0) {
36559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return 0;
36659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
36759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
36859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
36959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        if (epollResult < 0) {
37059abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
37159abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown            return -1;
37259abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        }
37359abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
37459abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown        mRequests.removeItemsAt(requestIndex);
37559abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    } // request lock
37659abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown    return 1;
37759abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown}
37859abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown
37959abe7e0909bf4b7bf7b9601e1e40a05f6d4fd8aJeff Brown} // namespace android
380