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