blob: d739f11f07551515481484928f5970a498f01427 [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 Brown7a0310e2015-03-10 18:31:12 -070023#include <inttypes.h>
Jeff Brown7901eb22010-09-13 23:17:30 -070024
25
26namespace android {
27
Jeff Brown3e2e38b2011-03-02 14:41:58 -080028// --- WeakMessageHandler ---
29
30WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
31 mHandler(handler) {
32}
33
Jeff Browndd1b0372012-05-31 16:15:35 -070034WeakMessageHandler::~WeakMessageHandler() {
35}
36
Jeff Brown3e2e38b2011-03-02 14:41:58 -080037void WeakMessageHandler::handleMessage(const Message& message) {
38 sp<MessageHandler> handler = mHandler.promote();
39 if (handler != NULL) {
40 handler->handleMessage(message);
41 }
42}
43
44
Jeff Browndd1b0372012-05-31 16:15:35 -070045// --- SimpleLooperCallback ---
46
Brian Carlstrom1693d7e2013-12-11 22:46:45 -080047SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
Jeff Browndd1b0372012-05-31 16:15:35 -070048 mCallback(callback) {
49}
50
51SimpleLooperCallback::~SimpleLooperCallback() {
52}
53
54int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
55 return mCallback(fd, events, data);
56}
57
58
Jeff Brown3e2e38b2011-03-02 14:41:58 -080059// --- Looper ---
60
Jeff Brown7901eb22010-09-13 23:17:30 -070061// Hint for number of file descriptors to be associated with the epoll instance.
62static const int EPOLL_SIZE_HINT = 8;
63
64// Maximum number of file descriptors for which to retrieve poll events each iteration.
65static const int EPOLL_MAX_EVENTS = 16;
66
Jeff Brownd1805182010-09-21 15:11:18 -070067static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
68static pthread_key_t gTLSKey = 0;
69
Jeff Brown7901eb22010-09-13 23:17:30 -070070Looper::Looper(bool allowNonCallbacks) :
Jeff Brown3e2e38b2011-03-02 14:41:58 -080071 mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
Jeff Browne7d54f82015-03-12 19:32:39 -070072 mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
Jeff Brown7a0310e2015-03-10 18:31:12 -070073 mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
Jeff Brown7901eb22010-09-13 23:17:30 -070074 int wakeFds[2];
75 int result = pipe(wakeFds);
76 LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
77
78 mWakeReadPipeFd = wakeFds[0];
79 mWakeWritePipeFd = wakeFds[1];
80
81 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
82 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
83 errno);
84
85 result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
86 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
87 errno);
88
Jeff Browne7d54f82015-03-12 19:32:39 -070089 AutoMutex _l(mLock);
90 rebuildEpollLocked();
Jeff Brown7901eb22010-09-13 23:17:30 -070091}
92
93Looper::~Looper() {
94 close(mWakeReadPipeFd);
95 close(mWakeWritePipeFd);
Jeff Browne7d54f82015-03-12 19:32:39 -070096 if (mEpollFd >= 0) {
97 close(mEpollFd);
98 }
Jeff Brown7901eb22010-09-13 23:17:30 -070099}
100
Jeff Brownd1805182010-09-21 15:11:18 -0700101void Looper::initTLSKey() {
102 int result = pthread_key_create(& gTLSKey, threadDestructor);
103 LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
104}
105
Jeff Brown7901eb22010-09-13 23:17:30 -0700106void Looper::threadDestructor(void *st) {
107 Looper* const self = static_cast<Looper*>(st);
108 if (self != NULL) {
109 self->decStrong((void*)threadDestructor);
110 }
111}
112
113void Looper::setForThread(const sp<Looper>& looper) {
114 sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
115
116 if (looper != NULL) {
117 looper->incStrong((void*)threadDestructor);
118 }
119
Jeff Brownd1805182010-09-21 15:11:18 -0700120 pthread_setspecific(gTLSKey, looper.get());
Jeff Brown7901eb22010-09-13 23:17:30 -0700121
122 if (old != NULL) {
123 old->decStrong((void*)threadDestructor);
124 }
125}
126
127sp<Looper> Looper::getForThread() {
Jeff Brownd1805182010-09-21 15:11:18 -0700128 int result = pthread_once(& gTLSOnce, initTLSKey);
129 LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
Jeff Brown7901eb22010-09-13 23:17:30 -0700130
Jeff Brownd1805182010-09-21 15:11:18 -0700131 return (Looper*)pthread_getspecific(gTLSKey);
Jeff Brown7901eb22010-09-13 23:17:30 -0700132}
133
134sp<Looper> Looper::prepare(int opts) {
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800135 bool allowNonCallbacks = opts & PREPARE_ALLOW_NON_CALLBACKS;
Jeff Brown7901eb22010-09-13 23:17:30 -0700136 sp<Looper> looper = Looper::getForThread();
137 if (looper == NULL) {
138 looper = new Looper(allowNonCallbacks);
139 Looper::setForThread(looper);
140 }
141 if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
Steve Block61d341b2012-01-05 23:22:43 +0000142 ALOGW("Looper already prepared for this thread with a different value for the "
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800143 "LOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
Jeff Brown7901eb22010-09-13 23:17:30 -0700144 }
145 return looper;
146}
147
148bool Looper::getAllowNonCallbacks() const {
149 return mAllowNonCallbacks;
150}
151
Jeff Browne7d54f82015-03-12 19:32:39 -0700152void Looper::rebuildEpollLocked() {
153 // Close old epoll instance if we have one.
154 if (mEpollFd >= 0) {
155#if DEBUG_CALLBACKS
156 ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
157#endif
158 close(mEpollFd);
159 }
160
161 // Allocate the new epoll instance and register the wake pipe.
162 mEpollFd = epoll_create(EPOLL_SIZE_HINT);
163 LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
164
165 struct epoll_event eventItem;
166 memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
167 eventItem.events = EPOLLIN;
168 eventItem.data.fd = mWakeReadPipeFd;
169 int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
170 LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
171 errno);
172
173 for (size_t i = 0; i < mRequests.size(); i++) {
174 const Request& request = mRequests.valueAt(i);
175 struct epoll_event eventItem;
176 request.initEventItem(&eventItem);
177
178 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
179 if (epollResult < 0) {
180 ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d",
181 request.fd, errno);
182 }
183 }
184}
185
186void Looper::scheduleEpollRebuildLocked() {
187 if (!mEpollRebuildRequired) {
188#if DEBUG_CALLBACKS
189 ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
190#endif
191 mEpollRebuildRequired = true;
192 wake();
193 }
194}
195
Jeff Brown7901eb22010-09-13 23:17:30 -0700196int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
197 int result = 0;
198 for (;;) {
199 while (mResponseIndex < mResponses.size()) {
200 const Response& response = mResponses.itemAt(mResponseIndex++);
Jeff Browndd1b0372012-05-31 16:15:35 -0700201 int ident = response.request.ident;
202 if (ident >= 0) {
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800203 int fd = response.request.fd;
204 int events = response.events;
205 void* data = response.request.data;
Jeff Brown7901eb22010-09-13 23:17:30 -0700206#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000207 ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800208 "fd=%d, events=0x%x, data=%p",
209 this, ident, fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700210#endif
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800211 if (outFd != NULL) *outFd = fd;
212 if (outEvents != NULL) *outEvents = events;
213 if (outData != NULL) *outData = data;
214 return ident;
Jeff Brown7901eb22010-09-13 23:17:30 -0700215 }
216 }
217
218 if (result != 0) {
219#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000220 ALOGD("%p ~ pollOnce - returning result %d", this, result);
Jeff Brown7901eb22010-09-13 23:17:30 -0700221#endif
222 if (outFd != NULL) *outFd = 0;
Jeff Browndd1b0372012-05-31 16:15:35 -0700223 if (outEvents != NULL) *outEvents = 0;
Jeff Brown7901eb22010-09-13 23:17:30 -0700224 if (outData != NULL) *outData = NULL;
225 return result;
226 }
227
228 result = pollInner(timeoutMillis);
229 }
230}
231
232int Looper::pollInner(int timeoutMillis) {
233#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000234 ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
Jeff Brown7901eb22010-09-13 23:17:30 -0700235#endif
Jeff Brown8d15c742010-10-05 15:35:37 -0700236
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800237 // Adjust the timeout based on when the next message is due.
238 if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
239 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown43550ee2011-03-17 01:34:19 -0700240 int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
241 if (messageTimeoutMillis >= 0
242 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
243 timeoutMillis = messageTimeoutMillis;
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800244 }
245#if DEBUG_POLL_AND_WAKE
Jeff Brown7a0310e2015-03-10 18:31:12 -0700246 ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800247 this, mNextMessageUptime - now, timeoutMillis);
248#endif
249 }
250
251 // Poll.
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800252 int result = POLL_WAKE;
Jeff Brown8d15c742010-10-05 15:35:37 -0700253 mResponses.clear();
254 mResponseIndex = 0;
255
Dianne Hackborn19159f92013-05-06 14:25:20 -0700256 // We are about to idle.
Jeff Brown27e57212015-02-26 14:16:30 -0800257 mPolling = true;
Dianne Hackborn19159f92013-05-06 14:25:20 -0700258
Jeff Brown7901eb22010-09-13 23:17:30 -0700259 struct epoll_event eventItems[EPOLL_MAX_EVENTS];
260 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
Jeff Brown8d15c742010-10-05 15:35:37 -0700261
Dianne Hackborn19159f92013-05-06 14:25:20 -0700262 // No longer idling.
Jeff Brown27e57212015-02-26 14:16:30 -0800263 mPolling = false;
Dianne Hackborn19159f92013-05-06 14:25:20 -0700264
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800265 // Acquire lock.
266 mLock.lock();
267
Jeff Browne7d54f82015-03-12 19:32:39 -0700268 // Rebuild epoll set if needed.
269 if (mEpollRebuildRequired) {
270 mEpollRebuildRequired = false;
271 rebuildEpollLocked();
272 goto Done;
273 }
274
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800275 // Check for poll error.
Jeff Brown7901eb22010-09-13 23:17:30 -0700276 if (eventCount < 0) {
Jeff Brown171bf9e2010-09-16 17:04:52 -0700277 if (errno == EINTR) {
Jeff Brown8d15c742010-10-05 15:35:37 -0700278 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700279 }
Steve Block61d341b2012-01-05 23:22:43 +0000280 ALOGW("Poll failed with an unexpected error, errno=%d", errno);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800281 result = POLL_ERROR;
Jeff Brown8d15c742010-10-05 15:35:37 -0700282 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700283 }
284
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800285 // Check for poll timeout.
Jeff Brown7901eb22010-09-13 23:17:30 -0700286 if (eventCount == 0) {
287#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000288 ALOGD("%p ~ pollOnce - timeout", this);
Jeff Brown7901eb22010-09-13 23:17:30 -0700289#endif
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800290 result = POLL_TIMEOUT;
Jeff Brown8d15c742010-10-05 15:35:37 -0700291 goto Done;
Jeff Brown7901eb22010-09-13 23:17:30 -0700292 }
293
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800294 // Handle all events.
Jeff Brown7901eb22010-09-13 23:17:30 -0700295#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000296 ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
Jeff Brown7901eb22010-09-13 23:17:30 -0700297#endif
Jeff Brown8d15c742010-10-05 15:35:37 -0700298
Jeff Brown9da18102010-09-17 17:01:23 -0700299 for (int i = 0; i < eventCount; i++) {
300 int fd = eventItems[i].data.fd;
301 uint32_t epollEvents = eventItems[i].events;
302 if (fd == mWakeReadPipeFd) {
303 if (epollEvents & EPOLLIN) {
Jeff Brown8d15c742010-10-05 15:35:37 -0700304 awoken();
Jeff Brown7901eb22010-09-13 23:17:30 -0700305 } else {
Steve Block61d341b2012-01-05 23:22:43 +0000306 ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
Jeff Brown9da18102010-09-17 17:01:23 -0700307 }
308 } else {
Jeff Brown9da18102010-09-17 17:01:23 -0700309 ssize_t requestIndex = mRequests.indexOfKey(fd);
310 if (requestIndex >= 0) {
311 int events = 0;
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800312 if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
313 if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
314 if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
315 if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
Jeff Brown8d15c742010-10-05 15:35:37 -0700316 pushResponse(events, mRequests.valueAt(requestIndex));
Jeff Brown9da18102010-09-17 17:01:23 -0700317 } else {
Steve Block61d341b2012-01-05 23:22:43 +0000318 ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
Jeff Brown9da18102010-09-17 17:01:23 -0700319 "no longer registered.", epollEvents, fd);
Jeff Brown7901eb22010-09-13 23:17:30 -0700320 }
321 }
322 }
Jeff Brown8d15c742010-10-05 15:35:37 -0700323Done: ;
Jeff Brown8d15c742010-10-05 15:35:37 -0700324
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800325 // Invoke pending message callbacks.
326 mNextMessageUptime = LLONG_MAX;
327 while (mMessageEnvelopes.size() != 0) {
328 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
329 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
330 if (messageEnvelope.uptime <= now) {
331 // Remove the envelope from the list.
332 // We keep a strong reference to the handler until the call to handleMessage
333 // finishes. Then we drop it so that the handler can be deleted *before*
334 // we reacquire our lock.
335 { // obtain handler
336 sp<MessageHandler> handler = messageEnvelope.handler;
337 Message message = messageEnvelope.message;
338 mMessageEnvelopes.removeAt(0);
339 mSendingMessage = true;
340 mLock.unlock();
341
342#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000343 ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800344 this, handler.get(), message.what);
345#endif
346 handler->handleMessage(message);
347 } // release handler
348
349 mLock.lock();
350 mSendingMessage = false;
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800351 result = POLL_CALLBACK;
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800352 } else {
353 // The last message left at the head of the queue determines the next wakeup time.
354 mNextMessageUptime = messageEnvelope.uptime;
355 break;
356 }
357 }
358
359 // Release lock.
360 mLock.unlock();
361
362 // Invoke all response callbacks.
Jeff Brown7901eb22010-09-13 23:17:30 -0700363 for (size_t i = 0; i < mResponses.size(); i++) {
Jeff Browndd1b0372012-05-31 16:15:35 -0700364 Response& response = mResponses.editItemAt(i);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800365 if (response.request.ident == POLL_CALLBACK) {
Jeff Brown3e2e38b2011-03-02 14:41:58 -0800366 int fd = response.request.fd;
367 int events = response.events;
368 void* data = response.request.data;
Jeff Brown7901eb22010-09-13 23:17:30 -0700369#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000370 ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
Jeff Browndd1b0372012-05-31 16:15:35 -0700371 this, response.request.callback.get(), fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700372#endif
Jeff Brown7a0310e2015-03-10 18:31:12 -0700373 // Invoke the callback. Note that the file descriptor may be closed by
374 // the callback (and potentially even reused) before the function returns so
375 // we need to be a little careful when removing the file descriptor afterwards.
Jeff Browndd1b0372012-05-31 16:15:35 -0700376 int callbackResult = response.request.callback->handleEvent(fd, events, data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700377 if (callbackResult == 0) {
Jeff Brown7a0310e2015-03-10 18:31:12 -0700378 removeFd(fd, response.request.seq);
Jeff Brown7901eb22010-09-13 23:17:30 -0700379 }
Jeff Brown7a0310e2015-03-10 18:31:12 -0700380
Jeff Browndd1b0372012-05-31 16:15:35 -0700381 // Clear the callback reference in the response structure promptly because we
382 // will not clear the response vector itself until the next poll.
383 response.request.callback.clear();
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800384 result = POLL_CALLBACK;
Jeff Brown7901eb22010-09-13 23:17:30 -0700385 }
386 }
387 return result;
388}
389
390int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
391 if (timeoutMillis <= 0) {
392 int result;
393 do {
394 result = pollOnce(timeoutMillis, outFd, outEvents, outData);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800395 } while (result == POLL_CALLBACK);
Jeff Brown7901eb22010-09-13 23:17:30 -0700396 return result;
397 } else {
398 nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
399 + milliseconds_to_nanoseconds(timeoutMillis);
400
401 for (;;) {
402 int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800403 if (result != POLL_CALLBACK) {
Jeff Brown7901eb22010-09-13 23:17:30 -0700404 return result;
405 }
406
Jeff Brown43550ee2011-03-17 01:34:19 -0700407 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
408 timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
409 if (timeoutMillis == 0) {
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800410 return POLL_TIMEOUT;
Jeff Brown7901eb22010-09-13 23:17:30 -0700411 }
Jeff Brown7901eb22010-09-13 23:17:30 -0700412 }
413 }
414}
415
416void Looper::wake() {
417#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000418 ALOGD("%p ~ wake", this);
Jeff Brown7901eb22010-09-13 23:17:30 -0700419#endif
420
Jeff Brown171bf9e2010-09-16 17:04:52 -0700421 ssize_t nWrite;
422 do {
423 nWrite = write(mWakeWritePipeFd, "W", 1);
424 } while (nWrite == -1 && errno == EINTR);
425
Jeff Brown7901eb22010-09-13 23:17:30 -0700426 if (nWrite != 1) {
427 if (errno != EAGAIN) {
Steve Block61d341b2012-01-05 23:22:43 +0000428 ALOGW("Could not write wake signal, errno=%d", errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700429 }
430 }
431}
432
Jeff Brown8d15c742010-10-05 15:35:37 -0700433void Looper::awoken() {
434#if DEBUG_POLL_AND_WAKE
Steve Blockeb095332011-12-20 16:23:08 +0000435 ALOGD("%p ~ awoken", this);
Jeff Brown8d15c742010-10-05 15:35:37 -0700436#endif
437
Jeff Brown8d15c742010-10-05 15:35:37 -0700438 char buffer[16];
439 ssize_t nRead;
440 do {
441 nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
442 } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
443}
444
445void Looper::pushResponse(int events, const Request& request) {
446 Response response;
447 response.events = events;
448 response.request = request;
449 mResponses.push(response);
450}
451
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800452int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
Jeff Browndd1b0372012-05-31 16:15:35 -0700453 return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
454}
455
456int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
Jeff Brown7901eb22010-09-13 23:17:30 -0700457#if DEBUG_CALLBACKS
Steve Blockeb095332011-12-20 16:23:08 +0000458 ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
Jeff Browndd1b0372012-05-31 16:15:35 -0700459 events, callback.get(), data);
Jeff Brown7901eb22010-09-13 23:17:30 -0700460#endif
461
Jeff Browndd1b0372012-05-31 16:15:35 -0700462 if (!callback.get()) {
Jeff Brown7901eb22010-09-13 23:17:30 -0700463 if (! mAllowNonCallbacks) {
Steve Block1b781ab2012-01-06 19:20:56 +0000464 ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
Jeff Brown7901eb22010-09-13 23:17:30 -0700465 return -1;
466 }
467
468 if (ident < 0) {
Jeff Browndd1b0372012-05-31 16:15:35 -0700469 ALOGE("Invalid attempt to set NULL callback with ident < 0.");
Jeff Brown7901eb22010-09-13 23:17:30 -0700470 return -1;
471 }
Jeff Browndd1b0372012-05-31 16:15:35 -0700472 } else {
Brian Carlstrom1693d7e2013-12-11 22:46:45 -0800473 ident = POLL_CALLBACK;
Jeff Brown7901eb22010-09-13 23:17:30 -0700474 }
475
476 { // acquire lock
477 AutoMutex _l(mLock);
478
479 Request request;
480 request.fd = fd;
481 request.ident = ident;
Jeff Browne7d54f82015-03-12 19:32:39 -0700482 request.events = events;
483 request.seq = mNextRequestSeq++;
Jeff Brown7901eb22010-09-13 23:17:30 -0700484 request.callback = callback;
485 request.data = data;
Jeff Brown7a0310e2015-03-10 18:31:12 -0700486 if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
Jeff Brown7901eb22010-09-13 23:17:30 -0700487
488 struct epoll_event eventItem;
Jeff Browne7d54f82015-03-12 19:32:39 -0700489 request.initEventItem(&eventItem);
Jeff Brown7901eb22010-09-13 23:17:30 -0700490
491 ssize_t requestIndex = mRequests.indexOfKey(fd);
492 if (requestIndex < 0) {
493 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
494 if (epollResult < 0) {
Steve Block1b781ab2012-01-06 19:20:56 +0000495 ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
Jeff Brown7901eb22010-09-13 23:17:30 -0700496 return -1;
497 }
498 mRequests.add(fd, request);
499 } else {
500 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
501 if (epollResult < 0) {
Jeff Brown7a0310e2015-03-10 18:31:12 -0700502 if (errno == ENOENT) {
Jeff Browne7d54f82015-03-12 19:32:39 -0700503 // Tolerate ENOENT because it means that an older file descriptor was
Jeff Brown7a0310e2015-03-10 18:31:12 -0700504 // closed before its callback was unregistered and meanwhile a new
505 // file descriptor with the same number has been created and is now
Jeff Browne7d54f82015-03-12 19:32:39 -0700506 // being registered for the first time. This error may occur naturally
507 // when a callback has the side-effect of closing the file descriptor
508 // before returning and unregistering itself. Callback sequence number
509 // checks further ensure that the race is benign.
510 //
511 // Unfortunately due to kernel limitations we need to rebuild the epoll
512 // set from scratch because it may contain an old file handle that we are
513 // now unable to remove since its file descriptor is no longer valid.
514 // No such problem would have occurred if we were using the poll system
515 // call instead, but that approach carries others disadvantages.
Jeff Brown7a0310e2015-03-10 18:31:12 -0700516#if DEBUG_CALLBACKS
517 ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
518 "being recycled, falling back on EPOLL_CTL_ADD, errno=%d",
519 this, errno);
520#endif
521 epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
522 if (epollResult < 0) {
523 ALOGE("Error modifying or adding epoll events for fd %d, errno=%d",
524 fd, errno);
525 return -1;
526 }
Jeff Browne7d54f82015-03-12 19:32:39 -0700527 scheduleEpollRebuildLocked();
Jeff Brown7a0310e2015-03-10 18:31:12 -0700528 } else {
529 ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
530 return -1;
531 }
Jeff Brown7901eb22010-09-13 23:17:30 -0700532 }
533 mRequests.replaceValueAt(requestIndex, request);
534 }
535 } // release lock
536 return 1;
537}
538
539int Looper::removeFd(int fd) {
Jeff Brown7a0310e2015-03-10 18:31:12 -0700540 return removeFd(fd, -1);
541}
542
543int Looper::removeFd(int fd, int seq) {
Jeff Brown7901eb22010-09-13 23:17:30 -0700544#if DEBUG_CALLBACKS
Jeff Brown7a0310e2015-03-10 18:31:12 -0700545 ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq);
Jeff Brown7901eb22010-09-13 23:17:30 -0700546#endif
547
548 { // acquire lock
549 AutoMutex _l(mLock);
550 ssize_t requestIndex = mRequests.indexOfKey(fd);
551 if (requestIndex < 0) {
552 return 0;
553 }
554
Jeff Brown7a0310e2015-03-10 18:31:12 -0700555 // Check the sequence number if one was given.
556 if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) {
557#if DEBUG_CALLBACKS
558 ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d",
559 this, mRequests.valueAt(requestIndex).seq);
560#endif
561 return 0;
Jeff Brown7901eb22010-09-13 23:17:30 -0700562 }
563
Jeff Brown7a0310e2015-03-10 18:31:12 -0700564 // Always remove the FD from the request map even if an error occurs while
565 // updating the epoll set so that we avoid accidentally leaking callbacks.
Jeff Brown7901eb22010-09-13 23:17:30 -0700566 mRequests.removeItemsAt(requestIndex);
Jeff Brown7a0310e2015-03-10 18:31:12 -0700567
568 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
569 if (epollResult < 0) {
570 if (seq != -1 && (errno == EBADF || errno == ENOENT)) {
Jeff Browne7d54f82015-03-12 19:32:39 -0700571 // Tolerate EBADF or ENOENT when the sequence number is known because it
Jeff Brown7a0310e2015-03-10 18:31:12 -0700572 // means that the file descriptor was closed before its callback was
Jeff Browne7d54f82015-03-12 19:32:39 -0700573 // unregistered. This error may occur naturally when a callback has the
574 // side-effect of closing the file descriptor before returning and
575 // unregistering itself.
576 //
577 // Unfortunately due to kernel limitations we need to rebuild the epoll
578 // set from scratch because it may contain an old file handle that we are
579 // now unable to remove since its file descriptor is no longer valid.
580 // No such problem would have occurred if we were using the poll system
581 // call instead, but that approach carries others disadvantages.
Jeff Brown7a0310e2015-03-10 18:31:12 -0700582#if DEBUG_CALLBACKS
583 ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor "
Jeff Browne7d54f82015-03-12 19:32:39 -0700584 "being closed, errno=%d", this, errno);
Jeff Brown7a0310e2015-03-10 18:31:12 -0700585#endif
Jeff Browne7d54f82015-03-12 19:32:39 -0700586 scheduleEpollRebuildLocked();
Jeff Brown7a0310e2015-03-10 18:31:12 -0700587 } else {
588 ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
589 return -1;
590 }
591 }
Jeff Brown8d15c742010-10-05 15:35:37 -0700592 } // release lock
Jeff Brown7901eb22010-09-13 23:17:30 -0700593 return 1;
594}
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
Jeff Brown7a0310e2015-03-10 18:31:12 -0700610 ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", 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 Brown27e57212015-02-26 14:16:30 -0800676bool Looper::isPolling() const {
677 return mPolling;
Dianne Hackborn19159f92013-05-06 14:25:20 -0700678}
679
Jeff Browne7d54f82015-03-12 19:32:39 -0700680void Looper::Request::initEventItem(struct epoll_event* eventItem) const {
681 int epollEvents = 0;
682 if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
683 if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
684
685 memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
686 eventItem->events = epollEvents;
687 eventItem->data.fd = fd;
688}
689
Jeff Brown7901eb22010-09-13 23:17:30 -0700690} // namespace android