xref: /aosp_15_r20/system/core/libutils/Looper.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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 #ifndef DEBUG_POLL_AND_WAKE
12 #define DEBUG_POLL_AND_WAKE 0
13 #endif
14 
15 // Debugs callback registration and invocation.
16 #ifndef DEBUG_CALLBACKS
17 #define DEBUG_CALLBACKS 0
18 #endif
19 
20 #include <utils/Looper.h>
21 
22 #include <sys/eventfd.h>
23 #include <cinttypes>
24 
25 namespace android {
26 
27 namespace {
28 
29 constexpr uint64_t WAKE_EVENT_FD_SEQ = 1;
30 
createEpollEvent(uint32_t events,uint64_t seq)31 epoll_event createEpollEvent(uint32_t events, uint64_t seq) {
32     return {.events = events, .data = {.u64 = seq}};
33 }
34 
35 }  // namespace
36 
37 // --- WeakMessageHandler ---
38 
WeakMessageHandler(const wp<MessageHandler> & handler)39 WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
40         mHandler(handler) {
41 }
42 
~WeakMessageHandler()43 WeakMessageHandler::~WeakMessageHandler() {
44 }
45 
handleMessage(const Message & message)46 void WeakMessageHandler::handleMessage(const Message& message) {
47     sp<MessageHandler> handler = mHandler.promote();
48     if (handler != nullptr) {
49         handler->handleMessage(message);
50     }
51 }
52 
53 
54 // --- SimpleLooperCallback ---
55 
SimpleLooperCallback(Looper_callbackFunc callback)56 SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
57         mCallback(callback) {
58 }
59 
~SimpleLooperCallback()60 SimpleLooperCallback::~SimpleLooperCallback() {
61 }
62 
handleEvent(int fd,int events,void * data)63 int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
64     return mCallback(fd, events, data);
65 }
66 
67 
68 // --- Looper ---
69 
70 // Maximum number of file descriptors for which to retrieve poll events each iteration.
71 static const int EPOLL_MAX_EVENTS = 16;
72 
73 thread_local static sp<Looper> gThreadLocalLooper;
74 
Looper(bool allowNonCallbacks)75 Looper::Looper(bool allowNonCallbacks)
76     : mAllowNonCallbacks(allowNonCallbacks),
77       mSendingMessage(false),
78       mPolling(false),
79       mEpollRebuildRequired(false),
80       mNextRequestSeq(WAKE_EVENT_FD_SEQ + 1),
81       mResponseIndex(0),
82       mNextMessageUptime(LLONG_MAX) {
83     mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
84     LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));
85 
86     AutoMutex _l(mLock);
87     rebuildEpollLocked();
88 }
89 
~Looper()90 Looper::~Looper() {
91 }
92 
setForThread(const sp<Looper> & looper)93 void Looper::setForThread(const sp<Looper>& looper) {
94     gThreadLocalLooper = looper;
95 }
96 
getForThread()97 sp<Looper> Looper::getForThread() {
98     return gThreadLocalLooper;
99 }
100 
prepare(int opts)101 sp<Looper> Looper::prepare(int opts) {
102     bool allowNonCallbacks = opts & PREPARE_ALLOW_NON_CALLBACKS;
103     sp<Looper> looper = Looper::getForThread();
104     if (looper == nullptr) {
105         looper = sp<Looper>::make(allowNonCallbacks);
106         Looper::setForThread(looper);
107     }
108     if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
109         ALOGW("Looper already prepared for this thread with a different value for the "
110                 "LOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
111     }
112     return looper;
113 }
114 
getAllowNonCallbacks() const115 bool Looper::getAllowNonCallbacks() const {
116     return mAllowNonCallbacks;
117 }
118 
rebuildEpollLocked()119 void Looper::rebuildEpollLocked() {
120     // Close old epoll instance if we have one.
121     if (mEpollFd >= 0) {
122 #if DEBUG_CALLBACKS
123         ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
124 #endif
125         mEpollFd.reset();
126     }
127 
128     // Allocate the new epoll instance and register the WakeEventFd.
129     mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
130     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
131 
132     epoll_event wakeEvent = createEpollEvent(EPOLLIN, WAKE_EVENT_FD_SEQ);
133     int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &wakeEvent);
134     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",
135                         strerror(errno));
136 
137     for (const auto& [seq, request] : mRequests) {
138         epoll_event eventItem = createEpollEvent(request.getEpollEvents(), seq);
139 
140         int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
141         if (epollResult < 0) {
142             ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
143                   request.fd, strerror(errno));
144         }
145     }
146 }
147 
scheduleEpollRebuildLocked()148 void Looper::scheduleEpollRebuildLocked() {
149     if (!mEpollRebuildRequired) {
150 #if DEBUG_CALLBACKS
151         ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
152 #endif
153         mEpollRebuildRequired = true;
154         wake();
155     }
156 }
157 
pollOnce(int timeoutMillis,int * outFd,int * outEvents,void ** outData)158 int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
159     int result = 0;
160     for (;;) {
161         while (mResponseIndex < mResponses.size()) {
162             const Response& response = mResponses.itemAt(mResponseIndex++);
163             int ident = response.request.ident;
164             if (ident >= 0) {
165                 int fd = response.request.fd;
166                 int events = response.events;
167                 void* data = response.request.data;
168 #if DEBUG_POLL_AND_WAKE
169                 ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
170                         "fd=%d, events=0x%x, data=%p",
171                         this, ident, fd, events, data);
172 #endif
173                 if (outFd != nullptr) *outFd = fd;
174                 if (outEvents != nullptr) *outEvents = events;
175                 if (outData != nullptr) *outData = data;
176                 return ident;
177             }
178         }
179 
180         if (result != 0) {
181 #if DEBUG_POLL_AND_WAKE
182             ALOGD("%p ~ pollOnce - returning result %d", this, result);
183 #endif
184             if (outFd != nullptr) *outFd = 0;
185             if (outEvents != nullptr) *outEvents = 0;
186             if (outData != nullptr) *outData = nullptr;
187             return result;
188         }
189 
190         result = pollInner(timeoutMillis);
191     }
192 }
193 
pollInner(int timeoutMillis)194 int Looper::pollInner(int timeoutMillis) {
195 #if DEBUG_POLL_AND_WAKE
196     ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
197 #endif
198 
199     // Adjust the timeout based on when the next message is due.
200     if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
201         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
202         int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
203         if (messageTimeoutMillis >= 0
204                 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
205             timeoutMillis = messageTimeoutMillis;
206         }
207 #if DEBUG_POLL_AND_WAKE
208         ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
209                 this, mNextMessageUptime - now, timeoutMillis);
210 #endif
211     }
212 
213     // Poll.
214     int result = POLL_WAKE;
215     mResponses.clear();
216     mResponseIndex = 0;
217 
218     // We are about to idle.
219     mPolling = true;
220 
221     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
222     int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
223 
224     // No longer idling.
225     mPolling = false;
226 
227     // Acquire lock.
228     mLock.lock();
229 
230     // Rebuild epoll set if needed.
231     if (mEpollRebuildRequired) {
232         mEpollRebuildRequired = false;
233         rebuildEpollLocked();
234         goto Done;
235     }
236 
237     // Check for poll error.
238     if (eventCount < 0) {
239         if (errno == EINTR) {
240             goto Done;
241         }
242         ALOGW("Poll failed with an unexpected error: %s", strerror(errno));
243         result = POLL_ERROR;
244         goto Done;
245     }
246 
247     // Check for poll timeout.
248     if (eventCount == 0) {
249 #if DEBUG_POLL_AND_WAKE
250         ALOGD("%p ~ pollOnce - timeout", this);
251 #endif
252         result = POLL_TIMEOUT;
253         goto Done;
254     }
255 
256     // Handle all events.
257 #if DEBUG_POLL_AND_WAKE
258     ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
259 #endif
260 
261     for (int i = 0; i < eventCount; i++) {
262         const SequenceNumber seq = eventItems[i].data.u64;
263         uint32_t epollEvents = eventItems[i].events;
264         if (seq == WAKE_EVENT_FD_SEQ) {
265             if (epollEvents & EPOLLIN) {
266                 awoken();
267             } else {
268                 ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
269             }
270         } else {
271             const auto& request_it = mRequests.find(seq);
272             if (request_it != mRequests.end()) {
273                 const auto& request = request_it->second;
274                 int events = 0;
275                 if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
276                 if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
277                 if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
278                 if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
279                 mResponses.push({.seq = seq, .events = events, .request = request});
280             } else {
281                 ALOGW("Ignoring unexpected epoll events 0x%x for sequence number %" PRIu64
282                       " that is no longer registered.",
283                       epollEvents, seq);
284             }
285         }
286     }
287 Done: ;
288 
289     // Invoke pending message callbacks.
290     mNextMessageUptime = LLONG_MAX;
291     while (mMessageEnvelopes.size() != 0) {
292         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
293         const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
294         if (messageEnvelope.uptime <= now) {
295             // Remove the envelope from the list.
296             // We keep a strong reference to the handler until the call to handleMessage
297             // finishes.  Then we drop it so that the handler can be deleted *before*
298             // we reacquire our lock.
299             { // obtain handler
300                 sp<MessageHandler> handler = messageEnvelope.handler;
301                 Message message = messageEnvelope.message;
302                 mMessageEnvelopes.removeAt(0);
303                 mSendingMessage = true;
304                 mLock.unlock();
305 
306 #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
307                 ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
308                         this, handler.get(), message.what);
309 #endif
310                 handler->handleMessage(message);
311             } // release handler
312 
313             mLock.lock();
314             mSendingMessage = false;
315             result = POLL_CALLBACK;
316         } else {
317             // The last message left at the head of the queue determines the next wakeup time.
318             mNextMessageUptime = messageEnvelope.uptime;
319             break;
320         }
321     }
322 
323     // Release lock.
324     mLock.unlock();
325 
326     // Invoke all response callbacks.
327     for (size_t i = 0; i < mResponses.size(); i++) {
328         Response& response = mResponses.editItemAt(i);
329         if (response.request.ident == POLL_CALLBACK) {
330             int fd = response.request.fd;
331             int events = response.events;
332             void* data = response.request.data;
333 #if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
334             ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
335                     this, response.request.callback.get(), fd, events, data);
336 #endif
337             // Invoke the callback.  Note that the file descriptor may be closed by
338             // the callback (and potentially even reused) before the function returns so
339             // we need to be a little careful when removing the file descriptor afterwards.
340             int callbackResult = response.request.callback->handleEvent(fd, events, data);
341             if (callbackResult == 0) {
342                 AutoMutex _l(mLock);
343                 removeSequenceNumberLocked(response.seq);
344             }
345 
346             // Clear the callback reference in the response structure promptly because we
347             // will not clear the response vector itself until the next poll.
348             response.request.callback.clear();
349             result = POLL_CALLBACK;
350         }
351     }
352     return result;
353 }
354 
pollAll(int timeoutMillis,int * outFd,int * outEvents,void ** outData)355 int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
356     if (timeoutMillis <= 0) {
357         int result;
358         do {
359             result = pollOnce(timeoutMillis, outFd, outEvents, outData);
360         } while (result == POLL_CALLBACK);
361         return result;
362     } else {
363         nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
364                 + milliseconds_to_nanoseconds(timeoutMillis);
365 
366         for (;;) {
367             int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
368             if (result != POLL_CALLBACK) {
369                 return result;
370             }
371 
372             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
373             timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
374             if (timeoutMillis == 0) {
375                 return POLL_TIMEOUT;
376             }
377         }
378     }
379 }
380 
wake()381 void Looper::wake() {
382 #if DEBUG_POLL_AND_WAKE
383     ALOGD("%p ~ wake", this);
384 #endif
385 
386     uint64_t inc = 1;
387     ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
388     if (nWrite != sizeof(uint64_t)) {
389         if (errno != EAGAIN) {
390             LOG_ALWAYS_FATAL("Could not write wake signal to fd %d (returned %zd): %s",
391                              mWakeEventFd.get(), nWrite, strerror(errno));
392         }
393     }
394 }
395 
awoken()396 void Looper::awoken() {
397 #if DEBUG_POLL_AND_WAKE
398     ALOGD("%p ~ awoken", this);
399 #endif
400 
401     uint64_t counter;
402     TEMP_FAILURE_RETRY(read(mWakeEventFd.get(), &counter, sizeof(uint64_t)));
403 }
404 
addFd(int fd,int ident,int events,Looper_callbackFunc callback,void * data)405 int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
406     sp<SimpleLooperCallback> looperCallback;
407     if (callback) {
408         looperCallback = sp<SimpleLooperCallback>::make(callback);
409     }
410     return addFd(fd, ident, events, looperCallback, data);
411 }
412 
addFd(int fd,int ident,int events,const sp<LooperCallback> & callback,void * data)413 int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
414 #if DEBUG_CALLBACKS
415     ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
416             events, callback.get(), data);
417 #endif
418 
419     if (!callback.get()) {
420         if (! mAllowNonCallbacks) {
421             ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
422             return -1;
423         }
424 
425         if (ident < 0) {
426             ALOGE("Invalid attempt to set NULL callback with ident < 0.");
427             return -1;
428         }
429     } else {
430         ident = POLL_CALLBACK;
431     }
432 
433     { // acquire lock
434         AutoMutex _l(mLock);
435         // There is a sequence number reserved for the WakeEventFd.
436         if (mNextRequestSeq == WAKE_EVENT_FD_SEQ) mNextRequestSeq++;
437         const SequenceNumber seq = mNextRequestSeq++;
438 
439         Request request;
440         request.fd = fd;
441         request.ident = ident;
442         request.events = events;
443         request.callback = callback;
444         request.data = data;
445 
446         epoll_event eventItem = createEpollEvent(request.getEpollEvents(), seq);
447         auto seq_it = mSequenceNumberByFd.find(fd);
448         if (seq_it == mSequenceNumberByFd.end()) {
449             int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
450             if (epollResult < 0) {
451                 ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));
452                 return -1;
453             }
454             mRequests.emplace(seq, request);
455             mSequenceNumberByFd.emplace(fd, seq);
456         } else {
457             int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_MOD, fd, &eventItem);
458             if (epollResult < 0) {
459                 if (errno == ENOENT) {
460                     // Tolerate ENOENT because it means that an older file descriptor was
461                     // closed before its callback was unregistered and meanwhile a new
462                     // file descriptor with the same number has been created and is now
463                     // being registered for the first time.  This error may occur naturally
464                     // when a callback has the side-effect of closing the file descriptor
465                     // before returning and unregistering itself.  Callback sequence number
466                     // checks further ensure that the race is benign.
467                     //
468                     // Unfortunately due to kernel limitations we need to rebuild the epoll
469                     // set from scratch because it may contain an old file handle that we are
470                     // now unable to remove since its file descriptor is no longer valid.
471                     // No such problem would have occurred if we were using the poll system
472                     // call instead, but that approach carries other disadvantages.
473 #if DEBUG_CALLBACKS
474                     ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
475                             "being recycled, falling back on EPOLL_CTL_ADD: %s",
476                             this, strerror(errno));
477 #endif
478                     epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
479                     if (epollResult < 0) {
480                         ALOGE("Error modifying or adding epoll events for fd %d: %s",
481                                 fd, strerror(errno));
482                         return -1;
483                     }
484                     scheduleEpollRebuildLocked();
485                 } else {
486                     ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));
487                     return -1;
488                 }
489             }
490             const SequenceNumber oldSeq = seq_it->second;
491             mRequests.erase(oldSeq);
492             mRequests.emplace(seq, request);
493             seq_it->second = seq;
494         }
495     } // release lock
496     return 1;
497 }
498 
getFdStateDebug(int fd,int * ident,int * events,sp<LooperCallback> * cb,void ** data)499 bool Looper::getFdStateDebug(int fd, int* ident, int* events, sp<LooperCallback>* cb, void** data) {
500     AutoMutex _l(mLock);
501     if (auto seqNumIt = mSequenceNumberByFd.find(fd); seqNumIt != mSequenceNumberByFd.cend()) {
502         if (auto reqIt = mRequests.find(seqNumIt->second); reqIt != mRequests.cend()) {
503             const Request& request = reqIt->second;
504             if (ident) *ident = request.ident;
505             if (events) *events = request.events;
506             if (cb) *cb = request.callback;
507             if (data) *data = request.data;
508             return true;
509         }
510     }
511     return false;
512 }
513 
removeFd(int fd)514 int Looper::removeFd(int fd) {
515     AutoMutex _l(mLock);
516     const auto& it = mSequenceNumberByFd.find(fd);
517     if (it == mSequenceNumberByFd.end()) {
518         return 0;
519     }
520     return removeSequenceNumberLocked(it->second);
521 }
522 
repoll(int fd)523 int Looper::repoll(int fd) {
524     AutoMutex _l(mLock);
525     const auto& it = mSequenceNumberByFd.find(fd);
526     if (it == mSequenceNumberByFd.end()) {
527         return 0;
528     }
529 
530     const auto& request_it = mRequests.find(it->second);
531     if (request_it == mRequests.end()) {
532         return 0;
533     }
534     const auto& [seq, request] = *request_it;
535 
536     LOG_ALWAYS_FATAL_IF(
537             fd != request.fd,
538             "Looper has inconsistent data structure. When looking up FD %d found FD %d.", fd,
539             request_it->second.fd);
540 
541     epoll_event eventItem = createEpollEvent(request.getEpollEvents(), seq);
542     if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_MOD, fd, &eventItem) == -1) return 0;
543 
544     return 1;  // success
545 }
546 
removeSequenceNumberLocked(SequenceNumber seq)547 int Looper::removeSequenceNumberLocked(SequenceNumber seq) {
548 #if DEBUG_CALLBACKS
549     ALOGD("%p ~ removeFd - seq=%" PRIu64, this, seq);
550 #endif
551 
552     const auto& request_it = mRequests.find(seq);
553     if (request_it == mRequests.end()) {
554         return 0;
555     }
556     const int fd = request_it->second.fd;
557 
558     // Always remove the FD from the request map even if an error occurs while
559     // updating the epoll set so that we avoid accidentally leaking callbacks.
560     mRequests.erase(request_it);
561     mSequenceNumberByFd.erase(fd);
562 
563     int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, nullptr);
564     if (epollResult < 0) {
565         if (errno == EBADF || errno == ENOENT) {
566             // Tolerate EBADF or ENOENT because it means that the file descriptor was closed
567             // before its callback was unregistered. This error may occur naturally when a
568             // callback has the side-effect of closing the file descriptor before returning and
569             // unregistering itself.
570             //
571             // Unfortunately due to kernel limitations we need to rebuild the epoll
572             // set from scratch because it may contain an old file handle that we are
573             // now unable to remove since its file descriptor is no longer valid.
574             // No such problem would have occurred if we were using the poll system
575             // call instead, but that approach carries other disadvantages.
576 #if DEBUG_CALLBACKS
577             ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor "
578                   "being closed: %s",
579                   this, strerror(errno));
580 #endif
581             scheduleEpollRebuildLocked();
582         } else {
583             // Some other error occurred.  This is really weird because it means
584             // our list of callbacks got out of sync with the epoll set somehow.
585             // We defensively rebuild the epoll set to avoid getting spurious
586             // notifications with nowhere to go.
587             ALOGE("Error removing epoll events for fd %d: %s", fd, strerror(errno));
588             scheduleEpollRebuildLocked();
589             return -1;
590         }
591     }
592     return 1;
593 }
594 
sendMessage(const sp<MessageHandler> & handler,const Message & message)595 void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
596     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
597     sendMessageAtTime(now, handler, message);
598 }
599 
sendMessageDelayed(nsecs_t uptimeDelay,const sp<MessageHandler> & handler,const Message & message)600 void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
601         const Message& message) {
602     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
603     sendMessageAtTime(now + uptimeDelay, handler, message);
604 }
605 
sendMessageAtTime(nsecs_t uptime,const sp<MessageHandler> & handler,const Message & message)606 void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
607         const Message& message) {
608 #if DEBUG_CALLBACKS
609     ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d",
610             this, uptime, handler.get(), message.what);
611 #endif
612 
613     size_t i = 0;
614     { // acquire lock
615         AutoMutex _l(mLock);
616 
617         size_t messageCount = mMessageEnvelopes.size();
618         while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
619             i += 1;
620         }
621 
622         MessageEnvelope messageEnvelope(uptime, handler, message);
623         mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
624 
625         // Optimization: If the Looper is currently sending a message, then we can skip
626         // the call to wake() because the next thing the Looper will do after processing
627         // messages is to decide when the next wakeup time should be.  In fact, it does
628         // not even matter whether this code is running on the Looper thread.
629         if (mSendingMessage) {
630             return;
631         }
632     } // release lock
633 
634     // Wake the poll loop only when we enqueue a new message at the head.
635     if (i == 0) {
636         wake();
637     }
638 }
639 
removeMessages(const sp<MessageHandler> & handler)640 void Looper::removeMessages(const sp<MessageHandler>& handler) {
641 #if DEBUG_CALLBACKS
642     ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
643 #endif
644 
645     { // acquire lock
646         AutoMutex _l(mLock);
647 
648         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
649             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
650             if (messageEnvelope.handler == handler) {
651                 mMessageEnvelopes.removeAt(i);
652             }
653         }
654     } // release lock
655 }
656 
removeMessages(const sp<MessageHandler> & handler,int what)657 void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
658 #if DEBUG_CALLBACKS
659     ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
660 #endif
661 
662     { // acquire lock
663         AutoMutex _l(mLock);
664 
665         for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
666             const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
667             if (messageEnvelope.handler == handler
668                     && messageEnvelope.message.what == what) {
669                 mMessageEnvelopes.removeAt(i);
670             }
671         }
672     } // release lock
673 }
674 
isPolling() const675 bool Looper::isPolling() const {
676     return mPolling;
677 }
678 
getEpollEvents() const679 uint32_t Looper::Request::getEpollEvents() const {
680     uint32_t epollEvents = 0;
681     if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
682     if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
683     return epollEvents;
684 }
685 
~MessageHandler()686 MessageHandler::~MessageHandler() { }
687 
~LooperCallback()688 LooperCallback::~LooperCallback() { }
689 
690 } // namespace android
691