Home | History | Annotate | Download | only in utils
      1 //
      2 // Copyright 2010 The Android Open Source Project
      3 //
      4 // A looper implementation based on epoll().
      5 //
      6 #define LOG_TAG "Looper"
      7 
      8 //#define LOG_NDEBUG 0
      9 
     10 // Debugs poll and wake interactions.
     11 #define DEBUG_POLL_AND_WAKE 0
     12 
     13 // Debugs callback registration and invocation.
     14 #define DEBUG_CALLBACKS 0
     15 
     16 #include <cutils/log.h>
     17 #include <utils/Looper.h>
     18 #include <utils/Timers.h>
     19 
     20 #include <unistd.h>
     21 #include <fcntl.h>
     22 #include <limits.h>
     23 
     24 
     25 namespace android {
     26 
     27 // --- WeakMessageHandler ---
     28 
     29 WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
     30         mHandler(handler) {
     31 }
     32 
     33 void WeakMessageHandler::handleMessage(const Message& message) {
     34     sp<MessageHandler> handler = mHandler.promote();
     35     if (handler != NULL) {
     36         handler->handleMessage(message);
     37     }
     38 }
     39 
     40 
     41 // --- Looper ---
     42 
     43 #ifdef LOOPER_USES_EPOLL
     44 // Hint for number of file descriptors to be associated with the epoll instance.
     45 static const int EPOLL_SIZE_HINT = 8;
     46 
     47 // Maximum number of file descriptors for which to retrieve poll events each iteration.
     48 static const int EPOLL_MAX_EVENTS = 16;
     49 #endif
     50 
     51 static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
     52 static pthread_key_t gTLSKey = 0;
     53 
     54 Looper::Looper(bool allowNonCallbacks) :
     55         mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
     56         mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
     57     int wakeFds[2];
     58     int result = pipe(wakeFds);
     59     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
     60 
     61     mWakeReadPipeFd = wakeFds[0];
     62     mWakeWritePipeFd = wakeFds[1];
     63 
     64     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
     65     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
     66             errno);
     67 
     68     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
     69     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
     70             errno);
     71 
     72 #ifdef LOOPER_USES_EPOLL
     73     // Allocate the epoll instance and register the wake pipe.
     74     mEpollFd = epoll_create(EPOLL_SIZE_HINT);
     75     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
     76 
     77     struct epoll_event eventItem;
     78     memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
     79     eventItem.events = EPOLLIN;
     80     eventItem.data.fd = mWakeReadPipeFd;
     81     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
     82     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
     83             errno);
     84 #else
     85     // Add the wake pipe to the head of the request list with a null callback.
     86     struct pollfd requestedFd;
     87     requestedFd.fd = mWakeReadPipeFd;
     88     requestedFd.events = POLLIN;
     89     mRequestedFds.push(requestedFd);
     90 
     91     Request request;
     92     request.fd = mWakeReadPipeFd;
     93     request.callback = NULL;
     94     request.ident = 0;
     95     request.data = NULL;
     96     mRequests.push(request);
     97 
     98     mPolling = false;
     99     mWaiters = 0;
    100 #endif
    101 
    102 #ifdef LOOPER_STATISTICS
    103     mPendingWakeTime = -1;
    104     mPendingWakeCount = 0;
    105     mSampledWakeCycles = 0;
    106     mSampledWakeCountSum = 0;
    107     mSampledWakeLatencySum = 0;
    108 
    109     mSampledPolls = 0;
    110     mSampledZeroPollCount = 0;
    111     mSampledZeroPollLatencySum = 0;
    112     mSampledTimeoutPollCount = 0;
    113     mSampledTimeoutPollLatencySum = 0;
    114 #endif
    115 }
    116 
    117 Looper::~Looper() {
    118     close(mWakeReadPipeFd);
    119     close(mWakeWritePipeFd);
    120 #ifdef LOOPER_USES_EPOLL
    121     close(mEpollFd);
    122 #endif
    123 }
    124 
    125 void Looper::initTLSKey() {
    126     int result = pthread_key_create(& gTLSKey, threadDestructor);
    127     LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
    128 }
    129 
    130 void Looper::threadDestructor(void *st) {
    131     Looper* const self = static_cast<Looper*>(st);
    132     if (self != NULL) {
    133         self->decStrong((void*)threadDestructor);
    134     }
    135 }
    136 
    137 void Looper::setForThread(const sp<Looper>& looper) {
    138     sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
    139 
    140     if (looper != NULL) {
    141         looper->incStrong((void*)threadDestructor);
    142     }
    143 
    144     pthread_setspecific(gTLSKey, looper.get());
    145 
    146     if (old != NULL) {
    147         old->decStrong((void*)threadDestructor);
    148     }
    149 }
    150 
    151 sp<Looper> Looper::getForThread() {
    152     int result = pthread_once(& gTLSOnce, initTLSKey);
    153     LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
    154 
    155     return (Looper*)pthread_getspecific(gTLSKey);
    156 }
    157 
    158 sp<Looper> Looper::prepare(int opts) {
    159     bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
    160     sp<Looper> looper = Looper::getForThread();
    161     if (looper == NULL) {
    162         looper = new Looper(allowNonCallbacks);
    163         Looper::setForThread(looper);
    164     }
    165     if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
    166         LOGW("Looper already prepared for this thread with a different value for the "
    167                 "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
    168     }
    169     return looper;
    170 }
    171 
    172 bool Looper::getAllowNonCallbacks() const {
    173     return mAllowNonCallbacks;
    174 }
    175 
    176 int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    177     int result = 0;
    178     for (;;) {
    179         while (mResponseIndex < mResponses.size()) {
    180             const Response& response = mResponses.itemAt(mResponseIndex++);
    181             ALooper_callbackFunc callback = response.request.callback;
    182             if (!callback) {
    183                 int ident = response.request.ident;
    184                 int fd = response.request.fd;
    185                 int events = response.events;
    186                 void* data = response.request.data;
    187 #if DEBUG_POLL_AND_WAKE
    188                 LOGD("%p ~ pollOnce - returning signalled identifier %d: "
    189                         "fd=%d, events=0x%x, data=%p",
    190                         this, ident, fd, events, data);
    191 #endif
    192                 if (outFd != NULL) *outFd = fd;
    193                 if (outEvents != NULL) *outEvents = events;
    194                 if (outData != NULL) *outData = data;
    195                 return ident;
    196             }
    197         }
    198 
    199         if (result != 0) {
    200 #if DEBUG_POLL_AND_WAKE
    201             LOGD("%p ~ pollOnce - returning result %d", this, result);
    202 #endif
    203             if (outFd != NULL) *outFd = 0;
    204             if (outEvents != NULL) *outEvents = NULL;
    205             if (outData != NULL) *outData = NULL;
    206             return result;
    207         }
    208 
    209         result = pollInner(timeoutMillis);
    210     }
    211 }
    212 
    213 int Looper::pollInner(int timeoutMillis) {
    214 #if DEBUG_POLL_AND_WAKE
    215     LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
    216 #endif
    217 
    218     // Adjust the timeout based on when the next message is due.
    219     if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
    220         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    221         int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
    222         if (messageTimeoutMillis >= 0
    223                 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
    224             timeoutMillis = messageTimeoutMillis;
    225         }
    226 #if DEBUG_POLL_AND_WAKE
    227         LOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
    228                 this, mNextMessageUptime - now, timeoutMillis);
    229 #endif
    230     }
    231 
    232     // Poll.
    233     int result = ALOOPER_POLL_WAKE;
    234     mResponses.clear();
    235     mResponseIndex = 0;
    236 
    237 #ifdef LOOPER_STATISTICS
    238     nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
    239 #endif
    240 
    241 #ifdef LOOPER_USES_EPOLL
    242     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    243     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    244 #else
    245     // Wait for wakeAndLock() waiters to run then set mPolling to true.
    246     mLock.lock();
    247     while (mWaiters != 0) {
    248         mResume.wait(mLock);
    249     }
    250     mPolling = true;
    251     mLock.unlock();
    252 
    253     size_t requestedCount = mRequestedFds.size();
    254     int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
    255 #endif
    256 
    257     // Acquire lock.
    258     mLock.lock();
    259 
    260     // Check for poll error.
    261     if (eventCount < 0) {
    262         if (errno == EINTR) {
    263             goto Done;
    264         }
    265         LOGW("Poll failed with an unexpected error, errno=%d", errno);
    266         result = ALOOPER_POLL_ERROR;
    267         goto Done;
    268     }
    269 
    270     // Check for poll timeout.
    271     if (eventCount == 0) {
    272 #if DEBUG_POLL_AND_WAKE
    273         LOGD("%p ~ pollOnce - timeout", this);
    274 #endif
    275         result = ALOOPER_POLL_TIMEOUT;
    276         goto Done;
    277     }
    278 
    279     // Handle all events.
    280 #if DEBUG_POLL_AND_WAKE
    281     LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
    282 #endif
    283 
    284 #ifdef LOOPER_USES_EPOLL
    285     for (int i = 0; i < eventCount; i++) {
    286         int fd = eventItems[i].data.fd;
    287         uint32_t epollEvents = eventItems[i].events;
    288         if (fd == mWakeReadPipeFd) {
    289             if (epollEvents & EPOLLIN) {
    290                 awoken();
    291             } else {
    292                 LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
    293             }
    294         } else {
    295             ssize_t requestIndex = mRequests.indexOfKey(fd);
    296             if (requestIndex >= 0) {
    297                 int events = 0;
    298                 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
    299                 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
    300                 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
    301                 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
    302                 pushResponse(events, mRequests.valueAt(requestIndex));
    303             } else {
    304                 LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
    305                         "no longer registered.", epollEvents, fd);
    306             }
    307         }
    308     }
    309 Done: ;
    310 #else
    311     for (size_t i = 0; i < requestedCount; i++) {
    312         const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
    313 
    314         short pollEvents = requestedFd.revents;
    315         if (pollEvents) {
    316             if (requestedFd.fd == mWakeReadPipeFd) {
    317                 if (pollEvents & POLLIN) {
    318                     awoken();
    319                 } else {
    320                     LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);
    321                 }
    322             } else {
    323                 int events = 0;
    324                 if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;
    325                 if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;
    326                 if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;
    327                 if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;
    328                 if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;
    329                 pushResponse(events, mRequests.itemAt(i));
    330             }
    331             if (--eventCount == 0) {
    332                 break;
    333             }
    334         }
    335     }
    336 Done:
    337     // Set mPolling to false and wake up the wakeAndLock() waiters.
    338     mPolling = false;
    339     if (mWaiters != 0) {
    340         mAwake.broadcast();
    341     }
    342 #endif
    343 
    344 #ifdef LOOPER_STATISTICS
    345     nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
    346     mSampledPolls += 1;
    347     if (timeoutMillis == 0) {
    348         mSampledZeroPollCount += 1;
    349         mSampledZeroPollLatencySum += pollEndTime - pollStartTime;
    350     } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) {
    351         mSampledTimeoutPollCount += 1;
    352         mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime
    353                 - milliseconds_to_nanoseconds(timeoutMillis);
    354     }
    355     if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) {
    356         LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout", this,
    357                 0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount,
    358                 0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount);
    359         mSampledPolls = 0;
    360         mSampledZeroPollCount = 0;
    361         mSampledZeroPollLatencySum = 0;
    362         mSampledTimeoutPollCount = 0;
    363         mSampledTimeoutPollLatencySum = 0;
    364     }
    365 #endif
    366 
    367     // Invoke pending message callbacks.
    368     mNextMessageUptime = LLONG_MAX;
    369     while (mMessageEnvelopes.size() != 0) {
    370         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    371         const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
    372         if (messageEnvelope.uptime <= now) {
    373             // Remove the envelope from the list.
    374             // We keep a strong reference to the handler until the call to handleMessage
    375             // finishes.  Then we drop it so that the handler can be deleted *before*
    376             // we reacquire our lock.
    377             { // obtain handler
    378                 sp<MessageHandler> handler = messageEnvelope.handler;
    379                 Message message = messageEnvelope.message;
    380                 mMessageEnvelopes.removeAt(0);
    381                 mSendingMessage = true;
    382                 mLock.unlock();
    383 
    384 #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
    385                 LOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
    386                         this, handler.get(), message.what);
    387 #endif
    388                 handler->handleMessage(message);
    389             } // release handler
    390 
    391             mLock.lock();
    392             mSendingMessage = false;
    393             result = ALOOPER_POLL_CALLBACK;
    394         } else {
    395             // The last message left at the head of the queue determines the next wakeup time.
    396             mNextMessageUptime = messageEnvelope.uptime;
    397             break;
    398         }
    399     }
    400 
    401     // Release lock.
    402     mLock.unlock();
    403 
    404     // Invoke all response callbacks.
    405     for (size_t i = 0; i < mResponses.size(); i++) {
    406         const Response& response = mResponses.itemAt(i);
    407         ALooper_callbackFunc callback = response.request.callback;
    408         if (callback) {
    409             int fd = response.request.fd;
    410             int events = response.events;
    411             void* data = response.request.data;
    412 #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
    413             LOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
    414                     this, callback, fd, events, data);
    415 #endif
    416             int callbackResult = callback(fd, events, data);
    417             if (callbackResult == 0) {
    418                 removeFd(fd);
    419             }
    420             result = ALOOPER_POLL_CALLBACK;
    421         }
    422     }
    423     return result;
    424 }
    425 
    426 int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    427     if (timeoutMillis <= 0) {
    428         int result;
    429         do {
    430             result = pollOnce(timeoutMillis, outFd, outEvents, outData);
    431         } while (result == ALOOPER_POLL_CALLBACK);
    432         return result;
    433     } else {
    434         nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
    435                 + milliseconds_to_nanoseconds(timeoutMillis);
    436 
    437         for (;;) {
    438             int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
    439             if (result != ALOOPER_POLL_CALLBACK) {
    440                 return result;
    441             }
    442 
    443             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    444             timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
    445             if (timeoutMillis == 0) {
    446                 return ALOOPER_POLL_TIMEOUT;
    447             }
    448         }
    449     }
    450 }
    451 
    452 void Looper::wake() {
    453 #if DEBUG_POLL_AND_WAKE
    454     LOGD("%p ~ wake", this);
    455 #endif
    456 
    457 #ifdef LOOPER_STATISTICS
    458     // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
    459     if (mPendingWakeCount++ == 0) {
    460         mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
    461     }
    462 #endif
    463 
    464     ssize_t nWrite;
    465     do {
    466         nWrite = write(mWakeWritePipeFd, "W", 1);
    467     } while (nWrite == -1 && errno == EINTR);
    468 
    469     if (nWrite != 1) {
    470         if (errno != EAGAIN) {
    471             LOGW("Could not write wake signal, errno=%d", errno);
    472         }
    473     }
    474 }
    475 
    476 void Looper::awoken() {
    477 #if DEBUG_POLL_AND_WAKE
    478     LOGD("%p ~ awoken", this);
    479 #endif
    480 
    481 #ifdef LOOPER_STATISTICS
    482     if (mPendingWakeCount == 0) {
    483         LOGD("%p ~ awoken: spurious!", this);
    484     } else {
    485         mSampledWakeCycles += 1;
    486         mSampledWakeCountSum += mPendingWakeCount;
    487         mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime;
    488         mPendingWakeCount = 0;
    489         mPendingWakeTime = -1;
    490         if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) {
    491             LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle", this,
    492                     0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles,
    493                     float(mSampledWakeCountSum) / mSampledWakeCycles);
    494             mSampledWakeCycles = 0;
    495             mSampledWakeCountSum = 0;
    496             mSampledWakeLatencySum = 0;
    497         }
    498     }
    499 #endif
    500 
    501     char buffer[16];
    502     ssize_t nRead;
    503     do {
    504         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
    505     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
    506 }
    507 
    508 void Looper::pushResponse(int events, const Request& request) {
    509     Response response;
    510     response.events = events;
    511     response.request = request;
    512     mResponses.push(response);
    513 }
    514 
    515 int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
    516 #if DEBUG_CALLBACKS
    517     LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
    518             events, callback, data);
    519 #endif
    520 
    521     if (! callback) {
    522         if (! mAllowNonCallbacks) {
    523             LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
    524             return -1;
    525         }
    526 
    527         if (ident < 0) {
    528             LOGE("Invalid attempt to set NULL callback with ident <= 0.");
    529             return -1;
    530         }
    531     }
    532 
    533 #ifdef LOOPER_USES_EPOLL
    534     int epollEvents = 0;
    535     if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
    536     if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
    537 
    538     { // acquire lock
    539         AutoMutex _l(mLock);
    540 
    541         Request request;
    542         request.fd = fd;
    543         request.ident = ident;
    544         request.callback = callback;
    545         request.data = data;
    546 
    547         struct epoll_event eventItem;
    548         memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    549         eventItem.events = epollEvents;
    550         eventItem.data.fd = fd;
    551 
    552         ssize_t requestIndex = mRequests.indexOfKey(fd);
    553         if (requestIndex < 0) {
    554             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
    555             if (epollResult < 0) {
    556                 LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
    557                 return -1;
    558             }
    559             mRequests.add(fd, request);
    560         } else {
    561             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
    562             if (epollResult < 0) {
    563                 LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
    564                 return -1;
    565             }
    566             mRequests.replaceValueAt(requestIndex, request);
    567         }
    568     } // release lock
    569 #else
    570     int pollEvents = 0;
    571     if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN;
    572     if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT;
    573 
    574     wakeAndLock(); // acquire lock
    575 
    576     struct pollfd requestedFd;
    577     requestedFd.fd = fd;
    578     requestedFd.events = pollEvents;
    579 
    580     Request request;
    581     request.fd = fd;
    582     request.ident = ident;
    583     request.callback = callback;
    584     request.data = data;
    585     ssize_t index = getRequestIndexLocked(fd);
    586     if (index < 0) {
    587         mRequestedFds.push(requestedFd);
    588         mRequests.push(request);
    589     } else {
    590         mRequestedFds.replaceAt(requestedFd, size_t(index));
    591         mRequests.replaceAt(request, size_t(index));
    592     }
    593 
    594     mLock.unlock(); // release lock
    595 #endif
    596     return 1;
    597 }
    598 
    599 int Looper::removeFd(int fd) {
    600 #if DEBUG_CALLBACKS
    601     LOGD("%p ~ removeFd - fd=%d", this, fd);
    602 #endif
    603 
    604 #ifdef LOOPER_USES_EPOLL
    605     { // acquire lock
    606         AutoMutex _l(mLock);
    607         ssize_t requestIndex = mRequests.indexOfKey(fd);
    608         if (requestIndex < 0) {
    609             return 0;
    610         }
    611 
    612         int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
    613         if (epollResult < 0) {
    614             LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
    615             return -1;
    616         }
    617 
    618         mRequests.removeItemsAt(requestIndex);
    619     } // release lock
    620     return 1;
    621 #else
    622     wakeAndLock(); // acquire lock
    623 
    624     ssize_t index = getRequestIndexLocked(fd);
    625     if (index >= 0) {
    626         mRequestedFds.removeAt(size_t(index));
    627         mRequests.removeAt(size_t(index));
    628     }
    629 
    630     mLock.unlock(); // release lock
    631     return index >= 0;
    632 #endif
    633 }
    634 
    635 #ifndef LOOPER_USES_EPOLL
    636 ssize_t Looper::getRequestIndexLocked(int fd) {
    637     size_t requestCount = mRequestedFds.size();
    638 
    639     for (size_t i = 0; i < requestCount; i++) {
    640         if (mRequestedFds.itemAt(i).fd == fd) {
    641             return i;
    642         }
    643     }
    644 
    645     return -1;
    646 }
    647 
    648 void Looper::wakeAndLock() {
    649     mLock.lock();
    650 
    651     mWaiters += 1;
    652     while (mPolling) {
    653         wake();
    654         mAwake.wait(mLock);
    655     }
    656 
    657     mWaiters -= 1;
    658     if (mWaiters == 0) {
    659         mResume.signal();
    660     }
    661 }
    662 #endif
    663 
    664 void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
    665     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    666     sendMessageAtTime(now, handler, message);
    667 }
    668 
    669 void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
    670         const Message& message) {
    671     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    672     sendMessageAtTime(now + uptimeDelay, handler, message);
    673 }
    674 
    675 void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
    676         const Message& message) {
    677 #if DEBUG_CALLBACKS
    678     LOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
    679             this, uptime, handler.get(), message.what);
    680 #endif
    681 
    682     size_t i = 0;
    683     { // acquire lock
    684         AutoMutex _l(mLock);
    685 
    686         size_t messageCount = mMessageEnvelopes.size();
    687         while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
    688             i += 1;
    689         }
    690 
    691         MessageEnvelope messageEnvelope(uptime, handler, message);
    692         mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
    693 
    694         // Optimization: If the Looper is currently sending a message, then we can skip
    695         // the call to wake() because the next thing the Looper will do after processing
    696         // messages is to decide when the next wakeup time should be.  In fact, it does
    697         // not even matter whether this code is running on the Looper thread.
    698         if (mSendingMessage) {
    699             return;
    700         }
    701     } // release lock
    702 
    703     // Wake the poll loop only when we enqueue a new message at the head.
    704     if (i == 0) {
    705         wake();
    706     }
    707 }
    708 
    709 void Looper::removeMessages(const sp<MessageHandler>& handler) {
    710 #if DEBUG_CALLBACKS
    711     LOGD("%p ~ removeMessages - handler=%p", this, handler.get());
    712 #endif
    713 
    714     { // acquire lock
    715         AutoMutex _l(mLock);
    716 
    717         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
    718             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
    719             if (messageEnvelope.handler == handler) {
    720                 mMessageEnvelopes.removeAt(i);
    721             }
    722         }
    723     } // release lock
    724 }
    725 
    726 void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
    727 #if DEBUG_CALLBACKS
    728     LOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
    729 #endif
    730 
    731     { // acquire lock
    732         AutoMutex _l(mLock);
    733 
    734         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
    735             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
    736             if (messageEnvelope.handler == handler
    737                     && messageEnvelope.message.what == what) {
    738                 mMessageEnvelopes.removeAt(i);
    739             }
    740         }
    741     } // release lock
    742 }
    743 
    744 } // namespace android
    745