blob: 95db28db00117e4aa7f946da0d46564a6308e538 [file] [log] [blame]
Jeff Brown7901eb22010-09-13 23:17:30 -07001//
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>
Jeff Brown3e2e38b2011-03-02 14:41:58 -080022#include <limits.h>
Jeff Brown7901eb22010-09-13 23:17:30 -070023
24
25namespace android {
26
Jeff Brown3e2e38b2011-03-02 14:41:58 -080027// --- WeakMessageHandler ---
28
29WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
30 mHandler(handler) {
31}
32
33void 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
Jeff Brown8d15c742010-10-05 15:35:37 -070043#ifdef LOOPER_USES_EPOLL
Jeff Brown7901eb22010-09-13 23:17:30 -070044// Hint for number of file descriptors to be associated with the epoll instance.
45static const int EPOLL_SIZE_HINT = 8;
46
47// Maximum number of file descriptors for which to retrieve poll events each iteration.
48static const int EPOLL_MAX_EVENTS = 16;
Jeff Brown8d15c742010-10-05 15:35:37 -070049#endif
Jeff Brown7901eb22010-09-13 23:17:30 -070050
Jeff Brownd1805182010-09-21 15:11:18 -070051static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
52static pthread_key_t gTLSKey = 0;
53
Jeff Brown7901eb22010-09-13 23:17:30 -070054Looper::Looper(bool allowNonCallbacks) :
Jeff Brown3e2e38b2011-03-02 14:41:58 -080055 mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
56 mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
Jeff Brown7901eb22010-09-13 23:17:30 -070057 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
Jeff Brown8d15c742010-10-05 15:35:37 -070072#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
Jeff Brown7901eb22010-09-13 23:17:30 -070077 struct epoll_event eventItem;
Jeff Brownd1805182010-09-21 15:11:18 -070078 memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
Jeff Brown7901eb22010-09-13 23:17:30 -070079 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);
Jeff Brown8d15c742010-10-05 15:35:37 -070084#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
Jeff Brown7901eb22010-09-13 23:17:30 -0700101}
102
103Looper::~Looper() {
104 close(mWakeReadPipeFd);
105 close(mWakeWritePipeFd);
Jeff Brown8d15c742010-10-05 15:35:37 -0700106#ifdef LOOPER_USES_EPOLL
Jeff Brown7901eb22010-09-13 23:17:30 -0700107 close(mEpollFd);
Jeff Brown8d15c742010-10-05 15:35:37 -0700108#endif
Jeff Brown7901eb22010-09-13 23:17:30 -0700109}
110
Jeff Brownd1805182010-09-21 15:11:18 -0700111void Looper::initTLSKey() {
112 int result = pthread_key_create(& gTLSKey, threadDestructor);
113 LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
114}
115
Jeff Brown7901eb22010-09-13 23:17:30 -0700116void Looper::threadDestructor(void *st) {
117 Looper* const self = static_cast<Looper*>(st);
118 if (self != NULL) {
119 self->decStrong((void*)threadDestructor);
120 }
121}
122
123void Looper::setForThread(const sp<Looper>& looper) {
124 sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
125
126 if (looper != NULL) {
127 looper->incStrong((void*)threadDestructor);
128 }
129
Jeff Brownd1805182010-09-21 15:11:18 -0700130 pthread_setspecific(gTLSKey, looper.get());
Jeff Brown7901eb22010-09-13 23:17:30 -0700131
132 if (old != NULL) {
133 old->decStrong((void*)threadDestructor);
134 }
135}
136
137sp<Looper> Looper::getForThread() {
Jeff Brownd1805182010-09-21 15:11:18 -0700138 int result = pthread_once(& gTLSOnce, initTLSKey);
139 LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
Jeff Brown7901eb22010-09-13 23:17:30 -0700140
Jeff Brownd1805182010-09-21 15:11:18 -0700141 return (Looper*)pthread_getspecific(gTLSKey);
Jeff Brown7901eb22010-09-13 23:17:30 -0700142}
143
144sp<Looper> Looper::prepare(int opts) {
145 bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
146 sp<Looper> looper = Looper::getForThread();
147 if (looper == NULL) {
148 looper = new Looper(allowNonCallbacks);
149 Looper::setForThread(looper);
150 }
151 if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
Steve Block61d341b2012-01-05 23:22:43 +0000152 ALOGW("Looper already prepared for this thread with a different value for the "
Jeff Brown7901eb22010-09-13 23:17:30 -0700153 "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
154 }
155 return looper;
156}
157
158bool Looper::getAllowNonCallbacks() const {
159 return mAllowNonCallbacks;
160}
161
162int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
163 int result = 0;
164 for (;;) {
165 while (mResponseIndex < mResponses.size()) {
166 const Response& response = mResponses.itemAt(mResponseIndex++);
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800167 ALooper_callbackFunc callback = response.request.callback;
168 if (!callback) {
169 int ident = response.request.ident;
170 int fd = response.request.fd;
171 int events = response.events;
172 void* data = response.request.data;
Jeff Brown7901eb22010-09-13 23:17:30 -0700173#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000174 ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800175 "fd=%d, events=0x%x, data=%p",
176 this, ident, fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700177#endif
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800178 if (outFd != NULL) *outFd = fd;
179 if (outEvents != NULL) *outEvents = events;
180 if (outData != NULL) *outData = data;
181 return ident;
Jeff Brown7901eb22010-09-13 23:17:30 -0700182 }
183 }
184
185 if (result != 0) {
186#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000187 ALOGD("%p ~ pollOnce - returning result %d", this, result);
Jeff Brown7901eb22010-09-13 23:17:30 -0700188#endif
189 if (outFd != NULL) *outFd = 0;
190 if (outEvents != NULL) *outEvents = NULL;
191 if (outData != NULL) *outData = NULL;
192 return result;
193 }
194
195 result = pollInner(timeoutMillis);
196 }
197}
198
199int Looper::pollInner(int timeoutMillis) {
200#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000201 ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
Jeff Brown7901eb22010-09-13 23:17:30 -0700202#endif
Jeff Brown8d15c742010-10-05 15:35:37 -0700203
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800204 // Adjust the timeout based on when the next message is due.
205 if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
206 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown43550ee2011-03-17 01:34:19 -0700207 int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
208 if (messageTimeoutMillis >= 0
209 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
210 timeoutMillis = messageTimeoutMillis;
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800211 }
212#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000213 ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800214 this, mNextMessageUptime - now, timeoutMillis);
215#endif
216 }
217
218 // Poll.
Jeff Brown8d15c742010-10-05 15:35:37 -0700219 int result = ALOOPER_POLL_WAKE;
220 mResponses.clear();
221 mResponseIndex = 0;
222
Jeff Brown8d15c742010-10-05 15:35:37 -0700223#ifdef LOOPER_USES_EPOLL
Jeff Brown7901eb22010-09-13 23:17:30 -0700224 struct epoll_event eventItems[EPOLL_MAX_EVENTS];
225 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
Jeff Brown8d15c742010-10-05 15:35:37 -0700226#else
227 // Wait for wakeAndLock() waiters to run then set mPolling to true.
228 mLock.lock();
229 while (mWaiters != 0) {
230 mResume.wait(mLock);
231 }
232 mPolling = true;
233 mLock.unlock();
234
235 size_t requestedCount = mRequestedFds.size();
236 int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
237#endif
238
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800239 // Acquire lock.
240 mLock.lock();
241
242 // Check for poll error.
Jeff Brown7901eb22010-09-13 23:17:30 -0700243 if (eventCount < 0) {
Jeff Brown171bf9e2010-09-16 17:04:52 -0700244 if (errno == EINTR) {
Jeff Brown8d15c742010-10-05 15:35:37 -0700245 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700246 }
Steve Block61d341b2012-01-05 23:22:43 +0000247 ALOGW("Poll failed with an unexpected error, errno=%d", errno);
Jeff Brown8d15c742010-10-05 15:35:37 -0700248 result = ALOOPER_POLL_ERROR;
249 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700250 }
251
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800252 // Check for poll timeout.
Jeff Brown7901eb22010-09-13 23:17:30 -0700253 if (eventCount == 0) {
254#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000255 ALOGD("%p ~ pollOnce - timeout", this);
Jeff Brown7901eb22010-09-13 23:17:30 -0700256#endif
Jeff Brown8d15c742010-10-05 15:35:37 -0700257 result = ALOOPER_POLL_TIMEOUT;
258 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700259 }
260
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800261 // Handle all events.
Jeff Brown7901eb22010-09-13 23:17:30 -0700262#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000263 ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
Jeff Brown7901eb22010-09-13 23:17:30 -0700264#endif
Jeff Brown8d15c742010-10-05 15:35:37 -0700265
266#ifdef LOOPER_USES_EPOLL
Jeff Brown9da18102010-09-17 17:01:23 -0700267 for (int i = 0; i < eventCount; i++) {
268 int fd = eventItems[i].data.fd;
269 uint32_t epollEvents = eventItems[i].events;
270 if (fd == mWakeReadPipeFd) {
271 if (epollEvents & EPOLLIN) {
Jeff Brown8d15c742010-10-05 15:35:37 -0700272 awoken();
Jeff Brown7901eb22010-09-13 23:17:30 -0700273 } else {
Steve Block61d341b2012-01-05 23:22:43 +0000274 ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
Jeff Brown9da18102010-09-17 17:01:23 -0700275 }
276 } else {
Jeff Brown9da18102010-09-17 17:01:23 -0700277 ssize_t requestIndex = mRequests.indexOfKey(fd);
278 if (requestIndex >= 0) {
279 int events = 0;
280 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
281 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
282 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
283 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
Jeff Brown8d15c742010-10-05 15:35:37 -0700284 pushResponse(events, mRequests.valueAt(requestIndex));
Jeff Brown9da18102010-09-17 17:01:23 -0700285 } else {
Steve Block61d341b2012-01-05 23:22:43 +0000286 ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
Jeff Brown9da18102010-09-17 17:01:23 -0700287 "no longer registered.", epollEvents, fd);
Jeff Brown7901eb22010-09-13 23:17:30 -0700288 }
289 }
290 }
Jeff Brown8d15c742010-10-05 15:35:37 -0700291Done: ;
292#else
293 for (size_t i = 0; i < requestedCount; i++) {
294 const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
295
296 short pollEvents = requestedFd.revents;
297 if (pollEvents) {
298 if (requestedFd.fd == mWakeReadPipeFd) {
299 if (pollEvents & POLLIN) {
300 awoken();
301 } else {
Steve Block61d341b2012-01-05 23:22:43 +0000302 ALOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);
Jeff Brown8d15c742010-10-05 15:35:37 -0700303 }
304 } else {
305 int events = 0;
306 if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;
307 if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;
308 if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;
309 if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;
310 if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;
311 pushResponse(events, mRequests.itemAt(i));
312 }
313 if (--eventCount == 0) {
314 break;
315 }
316 }
317 }
Jeff Brown8d15c742010-10-05 15:35:37 -0700318Done:
319 // Set mPolling to false and wake up the wakeAndLock() waiters.
Jeff Brown8d15c742010-10-05 15:35:37 -0700320 mPolling = false;
321 if (mWaiters != 0) {
322 mAwake.broadcast();
323 }
Jeff Brown8d15c742010-10-05 15:35:37 -0700324#endif
325
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800326 // Invoke pending message callbacks.
327 mNextMessageUptime = LLONG_MAX;
328 while (mMessageEnvelopes.size() != 0) {
329 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
330 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
331 if (messageEnvelope.uptime <= now) {
332 // Remove the envelope from the list.
333 // We keep a strong reference to the handler until the call to handleMessage
334 // finishes. Then we drop it so that the handler can be deleted *before*
335 // we reacquire our lock.
336 { // obtain handler
337 sp<MessageHandler> handler = messageEnvelope.handler;
338 Message message = messageEnvelope.message;
339 mMessageEnvelopes.removeAt(0);
340 mSendingMessage = true;
341 mLock.unlock();
342
343#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000344 ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800345 this, handler.get(), message.what);
346#endif
347 handler->handleMessage(message);
348 } // release handler
349
350 mLock.lock();
351 mSendingMessage = false;
352 result = ALOOPER_POLL_CALLBACK;
353 } else {
354 // The last message left at the head of the queue determines the next wakeup time.
355 mNextMessageUptime = messageEnvelope.uptime;
356 break;
357 }
358 }
359
360 // Release lock.
361 mLock.unlock();
362
363 // Invoke all response callbacks.
Jeff Brown7901eb22010-09-13 23:17:30 -0700364 for (size_t i = 0; i < mResponses.size(); i++) {
365 const Response& response = mResponses.itemAt(i);
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800366 ALooper_callbackFunc callback = response.request.callback;
367 if (callback) {
368 int fd = response.request.fd;
369 int events = response.events;
370 void* data = response.request.data;
Jeff Brown7901eb22010-09-13 23:17:30 -0700371#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000372 ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800373 this, callback, fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700374#endif
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800375 int callbackResult = callback(fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700376 if (callbackResult == 0) {
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800377 removeFd(fd);
Jeff Brown7901eb22010-09-13 23:17:30 -0700378 }
Jeff Brown7901eb22010-09-13 23:17:30 -0700379 result = ALOOPER_POLL_CALLBACK;
380 }
381 }
382 return result;
383}
384
385int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
386 if (timeoutMillis <= 0) {
387 int result;
388 do {
389 result = pollOnce(timeoutMillis, outFd, outEvents, outData);
390 } while (result == ALOOPER_POLL_CALLBACK);
391 return result;
392 } else {
393 nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
394 + milliseconds_to_nanoseconds(timeoutMillis);
395
396 for (;;) {
397 int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
398 if (result != ALOOPER_POLL_CALLBACK) {
399 return result;
400 }
401
Jeff Brown43550ee2011-03-17 01:34:19 -0700402 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
403 timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
404 if (timeoutMillis == 0) {
Jeff Brown7901eb22010-09-13 23:17:30 -0700405 return ALOOPER_POLL_TIMEOUT;
406 }
Jeff Brown7901eb22010-09-13 23:17:30 -0700407 }
408 }
409}
410
411void Looper::wake() {
412#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000413 ALOGD("%p ~ wake", this);
Jeff Brown7901eb22010-09-13 23:17:30 -0700414#endif
415
Jeff Brown171bf9e2010-09-16 17:04:52 -0700416 ssize_t nWrite;
417 do {
418 nWrite = write(mWakeWritePipeFd, "W", 1);
419 } while (nWrite == -1 && errno == EINTR);
420
Jeff Brown7901eb22010-09-13 23:17:30 -0700421 if (nWrite != 1) {
422 if (errno != EAGAIN) {
Steve Block61d341b2012-01-05 23:22:43 +0000423 ALOGW("Could not write wake signal, errno=%d", errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700424 }
425 }
426}
427
Jeff Brown8d15c742010-10-05 15:35:37 -0700428void Looper::awoken() {
429#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000430 ALOGD("%p ~ awoken", this);
Jeff Brown8d15c742010-10-05 15:35:37 -0700431#endif
432
Jeff Brown8d15c742010-10-05 15:35:37 -0700433 char buffer[16];
434 ssize_t nRead;
435 do {
436 nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
437 } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
438}
439
440void Looper::pushResponse(int events, const Request& request) {
441 Response response;
442 response.events = events;
443 response.request = request;
444 mResponses.push(response);
445}
446
Jeff Brown7901eb22010-09-13 23:17:30 -0700447int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
448#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000449 ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
Jeff Brown7901eb22010-09-13 23:17:30 -0700450 events, callback, data);
451#endif
452
Jeff Brown7901eb22010-09-13 23:17:30 -0700453 if (! callback) {
454 if (! mAllowNonCallbacks) {
Steve Block1b781ab2012-01-06 19:20:56 +0000455 ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
Jeff Brown7901eb22010-09-13 23:17:30 -0700456 return -1;
457 }
458
459 if (ident < 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000460 ALOGE("Invalid attempt to set NULL callback with ident <= 0.");
Jeff Brown7901eb22010-09-13 23:17:30 -0700461 return -1;
462 }
463 }
464
Jeff Brown8d15c742010-10-05 15:35:37 -0700465#ifdef LOOPER_USES_EPOLL
466 int epollEvents = 0;
467 if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
468 if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
469
Jeff Brown7901eb22010-09-13 23:17:30 -0700470 { // acquire lock
471 AutoMutex _l(mLock);
472
473 Request request;
474 request.fd = fd;
475 request.ident = ident;
476 request.callback = callback;
477 request.data = data;
478
479 struct epoll_event eventItem;
Jeff Brownd1805182010-09-21 15:11:18 -0700480 memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
Jeff Brown7901eb22010-09-13 23:17:30 -0700481 eventItem.events = epollEvents;
482 eventItem.data.fd = fd;
483
484 ssize_t requestIndex = mRequests.indexOfKey(fd);
485 if (requestIndex < 0) {
486 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
487 if (epollResult < 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000488 ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700489 return -1;
490 }
491 mRequests.add(fd, request);
492 } else {
493 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
494 if (epollResult < 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000495 ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700496 return -1;
497 }
498 mRequests.replaceValueAt(requestIndex, request);
499 }
500 } // release lock
Jeff Brown8d15c742010-10-05 15:35:37 -0700501#else
502 int pollEvents = 0;
503 if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN;
504 if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT;
505
506 wakeAndLock(); // acquire lock
507
508 struct pollfd requestedFd;
509 requestedFd.fd = fd;
510 requestedFd.events = pollEvents;
511
512 Request request;
513 request.fd = fd;
514 request.ident = ident;
515 request.callback = callback;
516 request.data = data;
517 ssize_t index = getRequestIndexLocked(fd);
518 if (index < 0) {
519 mRequestedFds.push(requestedFd);
520 mRequests.push(request);
521 } else {
522 mRequestedFds.replaceAt(requestedFd, size_t(index));
523 mRequests.replaceAt(request, size_t(index));
524 }
525
526 mLock.unlock(); // release lock
527#endif
Jeff Brown7901eb22010-09-13 23:17:30 -0700528 return 1;
529}
530
531int Looper::removeFd(int fd) {
532#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000533 ALOGD("%p ~ removeFd - fd=%d", this, fd);
Jeff Brown7901eb22010-09-13 23:17:30 -0700534#endif
535
Jeff Brown8d15c742010-10-05 15:35:37 -0700536#ifdef LOOPER_USES_EPOLL
Jeff Brown7901eb22010-09-13 23:17:30 -0700537 { // acquire lock
538 AutoMutex _l(mLock);
539 ssize_t requestIndex = mRequests.indexOfKey(fd);
540 if (requestIndex < 0) {
541 return 0;
542 }
543
544 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
545 if (epollResult < 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000546 ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700547 return -1;
548 }
549
550 mRequests.removeItemsAt(requestIndex);
Jeff Brown8d15c742010-10-05 15:35:37 -0700551 } // release lock
Jeff Brown7901eb22010-09-13 23:17:30 -0700552 return 1;
Jeff Brown8d15c742010-10-05 15:35:37 -0700553#else
554 wakeAndLock(); // acquire lock
555
556 ssize_t index = getRequestIndexLocked(fd);
557 if (index >= 0) {
558 mRequestedFds.removeAt(size_t(index));
559 mRequests.removeAt(size_t(index));
560 }
561
562 mLock.unlock(); // release lock
563 return index >= 0;
564#endif
Jeff Brown7901eb22010-09-13 23:17:30 -0700565}
566
Jeff Brown8d15c742010-10-05 15:35:37 -0700567#ifndef LOOPER_USES_EPOLL
568ssize_t Looper::getRequestIndexLocked(int fd) {
569 size_t requestCount = mRequestedFds.size();
570
571 for (size_t i = 0; i < requestCount; i++) {
572 if (mRequestedFds.itemAt(i).fd == fd) {
573 return i;
574 }
575 }
576
577 return -1;
578}
579
580void Looper::wakeAndLock() {
581 mLock.lock();
582
583 mWaiters += 1;
584 while (mPolling) {
585 wake();
586 mAwake.wait(mLock);
587 }
588
589 mWaiters -= 1;
590 if (mWaiters == 0) {
591 mResume.signal();
592 }
593}
594#endif
595
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800596void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
Jeff Brownaa13c1b2011-04-12 22:39:53 -0700597 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
598 sendMessageAtTime(now, handler, message);
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800599}
600
601void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
602 const Message& message) {
603 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
604 sendMessageAtTime(now + uptimeDelay, handler, message);
605}
606
607void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
608 const Message& message) {
609#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000610 ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800611 this, uptime, handler.get(), message.what);
612#endif
613
614 size_t i = 0;
615 { // acquire lock
616 AutoMutex _l(mLock);
617
618 size_t messageCount = mMessageEnvelopes.size();
619 while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
620 i += 1;
621 }
622
623 MessageEnvelope messageEnvelope(uptime, handler, message);
624 mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
625
626 // Optimization: If the Looper is currently sending a message, then we can skip
627 // the call to wake() because the next thing the Looper will do after processing
628 // messages is to decide when the next wakeup time should be. In fact, it does
629 // not even matter whether this code is running on the Looper thread.
630 if (mSendingMessage) {
631 return;
632 }
633 } // release lock
634
635 // Wake the poll loop only when we enqueue a new message at the head.
636 if (i == 0) {
637 wake();
638 }
639}
640
641void Looper::removeMessages(const sp<MessageHandler>& handler) {
642#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000643 ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800644#endif
645
646 { // acquire lock
647 AutoMutex _l(mLock);
648
649 for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
650 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
651 if (messageEnvelope.handler == handler) {
652 mMessageEnvelopes.removeAt(i);
653 }
654 }
655 } // release lock
656}
657
658void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
659#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000660 ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800661#endif
662
663 { // acquire lock
664 AutoMutex _l(mLock);
665
666 for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
667 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
668 if (messageEnvelope.handler == handler
669 && messageEnvelope.message.what == what) {
670 mMessageEnvelopes.removeAt(i);
671 }
672 }
673 } // release lock
674}
675
Jeff Brown7901eb22010-09-13 23:17:30 -0700676} // namespace android