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
WeakMessageHandler(const wp<MessageHandler> & handler)29 WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
30 mHandler(handler) {
31 }
32
handleMessage(const Message & message)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
Looper(bool allowNonCallbacks)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
~Looper()117 Looper::~Looper() {
118 close(mWakeReadPipeFd);
119 close(mWakeWritePipeFd);
120 #ifdef LOOPER_USES_EPOLL
121 close(mEpollFd);
122 #endif
123 }
124
initTLSKey()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
threadDestructor(void * st)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
setForThread(const sp<Looper> & looper)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
getForThread()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
prepare(int opts)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
getAllowNonCallbacks() const172 bool Looper::getAllowNonCallbacks() const {
173 return mAllowNonCallbacks;
174 }
175
pollOnce(int timeoutMillis,int * outFd,int * outEvents,void ** outData)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
pollInner(int timeoutMillis)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
pollAll(int timeoutMillis,int * outFd,int * outEvents,void ** outData)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
wake()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
awoken()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
pushResponse(int events,const Request & request)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
addFd(int fd,int ident,int events,ALooper_callbackFunc callback,void * data)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
removeFd(int fd)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
getRequestIndexLocked(int fd)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
wakeAndLock()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
sendMessage(const sp<MessageHandler> & handler,const Message & message)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
sendMessageDelayed(nsecs_t uptimeDelay,const sp<MessageHandler> & handler,const Message & message)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
sendMessageAtTime(nsecs_t uptime,const sp<MessageHandler> & handler,const Message & message)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
removeMessages(const sp<MessageHandler> & handler)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
removeMessages(const sp<MessageHandler> & handler,int what)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