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