• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef UTILS_LOOPER_H
18 #define UTILS_LOOPER_H
19 
20 #include <utils/threads.h>
21 #include <utils/RefBase.h>
22 #include <utils/KeyedVector.h>
23 #include <utils/Timers.h>
24 
25 #include <android/looper.h>
26 
27 // When defined, uses epoll_wait() for polling, otherwise uses poll().
28 #define LOOPER_USES_EPOLL
29 
30 // When defined, logs performance statistics for tuning and debugging purposes.
31 //#define LOOPER_STATISTICS
32 
33 #ifdef LOOPER_USES_EPOLL
34 #include <sys/epoll.h>
35 #else
36 #include <sys/poll.h>
37 #endif
38 
39 /*
40  * Declare a concrete type for the NDK's looper forward declaration.
41  */
42 struct ALooper {
43 };
44 
45 namespace android {
46 
47 /**
48  * A message that can be posted to a Looper.
49  */
50 struct Message {
MessageMessage51     Message() : what(0) { }
MessageMessage52     Message(int what) : what(what) { }
53 
54     /* The message type. (interpretation is left up to the handler) */
55     int what;
56 };
57 
58 
59 /**
60  * Interface for a Looper message handler.
61  *
62  * The Looper holds a strong reference to the message handler whenever it has
63  * a message to deliver to it.  Make sure to call Looper::removeMessages
64  * to remove any pending messages destined for the handler so that the handler
65  * can be destroyed.
66  */
67 class MessageHandler : public virtual RefBase {
68 protected:
~MessageHandler()69     virtual ~MessageHandler() { }
70 
71 public:
72     /**
73      * Handles a message.
74      */
75     virtual void handleMessage(const Message& message) = 0;
76 };
77 
78 
79 /**
80  * A simple proxy that holds a weak reference to a message handler.
81  */
82 class WeakMessageHandler : public MessageHandler {
83 public:
84     WeakMessageHandler(const wp<MessageHandler>& handler);
85     virtual void handleMessage(const Message& message);
86 
87 private:
88     wp<MessageHandler> mHandler;
89 };
90 
91 
92 /**
93  * A polling loop that supports monitoring file descriptor events, optionally
94  * using callbacks.  The implementation uses epoll() internally.
95  *
96  * A looper can be associated with a thread although there is no requirement that it must be.
97  */
98 class Looper : public ALooper, public RefBase {
99 protected:
100     virtual ~Looper();
101 
102 public:
103     /**
104      * Creates a looper.
105      *
106      * If allowNonCallbaks is true, the looper will allow file descriptors to be
107      * registered without associated callbacks.  This assumes that the caller of
108      * pollOnce() is prepared to handle callback-less events itself.
109      */
110     Looper(bool allowNonCallbacks);
111 
112     /**
113      * Returns whether this looper instance allows the registration of file descriptors
114      * using identifiers instead of callbacks.
115      */
116     bool getAllowNonCallbacks() const;
117 
118     /**
119      * Waits for events to be available, with optional timeout in milliseconds.
120      * Invokes callbacks for all file descriptors on which an event occurred.
121      *
122      * If the timeout is zero, returns immediately without blocking.
123      * If the timeout is negative, waits indefinitely until an event appears.
124      *
125      * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
126      * the timeout expired and no callbacks were invoked and no other file
127      * descriptors were ready.
128      *
129      * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
130      *
131      * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
132      * timeout expired.
133      *
134      * Returns ALOOPER_POLL_ERROR if an error occurred.
135      *
136      * Returns a value >= 0 containing an identifier if its file descriptor has data
137      * and it has no callback function (requiring the caller here to handle it).
138      * In this (and only this) case outFd, outEvents and outData will contain the poll
139      * events and data associated with the fd, otherwise they will be set to NULL.
140      *
141      * This method does not return until it has finished invoking the appropriate callbacks
142      * for all file descriptors that were signalled.
143      */
144     int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
pollOnce(int timeoutMillis)145     inline int pollOnce(int timeoutMillis) {
146         return pollOnce(timeoutMillis, NULL, NULL, NULL);
147     }
148 
149     /**
150      * Like pollOnce(), but performs all pending callbacks until all
151      * data has been consumed or a file descriptor is available with no callback.
152      * This function will never return ALOOPER_POLL_CALLBACK.
153      */
154     int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
pollAll(int timeoutMillis)155     inline int pollAll(int timeoutMillis) {
156         return pollAll(timeoutMillis, NULL, NULL, NULL);
157     }
158 
159     /**
160      * Wakes the poll asynchronously.
161      *
162      * This method can be called on any thread.
163      * This method returns immediately.
164      */
165     void wake();
166 
167     /**
168      * Adds a new file descriptor to be polled by the looper.
169      * If the same file descriptor was previously added, it is replaced.
170      *
171      * "fd" is the file descriptor to be added.
172      * "ident" is an identifier for this event, which is returned from ALooper_pollOnce().
173      * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
174      * "events" are the poll events to wake up on.  Typically this is ALOOPER_EVENT_INPUT.
175      * "callback" is the function to call when there is an event on the file descriptor.
176      * "data" is a private data pointer to supply to the callback.
177      *
178      * There are two main uses of this function:
179      *
180      * (1) If "callback" is non-NULL, then this function will be called when there is
181      * data on the file descriptor.  It should execute any events it has pending,
182      * appropriately reading from the file descriptor.  The 'ident' is ignored in this case.
183      *
184      * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
185      * when its file descriptor has data available, requiring the caller to take
186      * care of processing it.
187      *
188      * Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
189      *
190      * This method can be called on any thread.
191      * This method may block briefly if it needs to wake the poll.
192      */
193     int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data);
194 
195     /**
196      * Removes a previously added file descriptor from the looper.
197      *
198      * When this method returns, it is safe to close the file descriptor since the looper
199      * will no longer have a reference to it.  However, it is possible for the callback to
200      * already be running or for it to run one last time if the file descriptor was already
201      * signalled.  Calling code is responsible for ensuring that this case is safely handled.
202      * For example, if the callback takes care of removing itself during its own execution either
203      * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
204      * again at any later time unless registered anew.
205      *
206      * Returns 1 if the file descriptor was removed, 0 if none was previously registered.
207      *
208      * This method can be called on any thread.
209      * This method may block briefly if it needs to wake the poll.
210      */
211     int removeFd(int fd);
212 
213     /**
214      * Enqueues a message to be processed by the specified handler.
215      *
216      * The handler must not be null.
217      * This method can be called on any thread.
218      */
219     void sendMessage(const sp<MessageHandler>& handler, const Message& message);
220 
221     /**
222      * Enqueues a message to be processed by the specified handler after all pending messages
223      * after the specified delay.
224      *
225      * The time delay is specified in uptime nanoseconds.
226      * The handler must not be null.
227      * This method can be called on any thread.
228      */
229     void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
230             const Message& message);
231 
232     /**
233      * Enqueues a message to be processed by the specified handler after all pending messages
234      * at the specified time.
235      *
236      * The time is specified in uptime nanoseconds.
237      * The handler must not be null.
238      * This method can be called on any thread.
239      */
240     void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
241             const Message& message);
242 
243     /**
244      * Removes all messages for the specified handler from the queue.
245      *
246      * The handler must not be null.
247      * This method can be called on any thread.
248      */
249     void removeMessages(const sp<MessageHandler>& handler);
250 
251     /**
252      * Removes all messages of a particular type for the specified handler from the queue.
253      *
254      * The handler must not be null.
255      * This method can be called on any thread.
256      */
257     void removeMessages(const sp<MessageHandler>& handler, int what);
258 
259     /**
260      * Prepares a looper associated with the calling thread, and returns it.
261      * If the thread already has a looper, it is returned.  Otherwise, a new
262      * one is created, associated with the thread, and returned.
263      *
264      * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
265      */
266     static sp<Looper> prepare(int opts);
267 
268     /**
269      * Sets the given looper to be associated with the calling thread.
270      * If another looper is already associated with the thread, it is replaced.
271      *
272      * If "looper" is NULL, removes the currently associated looper.
273      */
274     static void setForThread(const sp<Looper>& looper);
275 
276     /**
277      * Returns the looper associated with the calling thread, or NULL if
278      * there is not one.
279      */
280     static sp<Looper> getForThread();
281 
282 private:
283     struct Request {
284         int fd;
285         int ident;
286         ALooper_callbackFunc callback;
287         void* data;
288     };
289 
290     struct Response {
291         int events;
292         Request request;
293     };
294 
295     struct MessageEnvelope {
MessageEnvelopeMessageEnvelope296         MessageEnvelope() : uptime(0) { }
297 
MessageEnvelopeMessageEnvelope298         MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
299                 const Message& message) : uptime(uptime), handler(handler), message(message) {
300         }
301 
302         nsecs_t uptime;
303         sp<MessageHandler> handler;
304         Message message;
305     };
306 
307     const bool mAllowNonCallbacks; // immutable
308 
309     int mWakeReadPipeFd;  // immutable
310     int mWakeWritePipeFd; // immutable
311     Mutex mLock;
312 
313     Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
314     bool mSendingMessage; // guarded by mLock
315 
316 #ifdef LOOPER_USES_EPOLL
317     int mEpollFd; // immutable
318 
319     // Locked list of file descriptor monitoring requests.
320     KeyedVector<int, Request> mRequests;  // guarded by mLock
321 #else
322     // The lock guards state used to track whether there is a poll() in progress and whether
323     // there are any other threads waiting in wakeAndLock().  The condition variables
324     // are used to transfer control among these threads such that all waiters are
325     // serviced before a new poll can begin.
326     // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake
327     // until mPolling becomes false, then decrements mWaiters again.
328     // The poll() method blocks on mResume until mWaiters becomes 0, then sets
329     // mPolling to true, blocks until the poll completes, then resets mPolling to false
330     // and signals mResume if there are waiters.
331     bool mPolling;      // guarded by mLock
332     uint32_t mWaiters;  // guarded by mLock
333     Condition mAwake;   // guarded by mLock
334     Condition mResume;  // guarded by mLock
335 
336     Vector<struct pollfd> mRequestedFds;  // must hold mLock and mPolling must be false to modify
337     Vector<Request> mRequests;            // must hold mLock and mPolling must be false to modify
338 
339     ssize_t getRequestIndexLocked(int fd);
340     void wakeAndLock();
341 #endif
342 
343 #ifdef LOOPER_STATISTICS
344     static const int SAMPLED_WAKE_CYCLES_TO_AGGREGATE = 100;
345     static const int SAMPLED_POLLS_TO_AGGREGATE = 1000;
346 
347     nsecs_t mPendingWakeTime;
348     int mPendingWakeCount;
349 
350     int mSampledWakeCycles;
351     int mSampledWakeCountSum;
352     nsecs_t mSampledWakeLatencySum;
353 
354     int mSampledPolls;
355     int mSampledZeroPollCount;
356     int mSampledZeroPollLatencySum;
357     int mSampledTimeoutPollCount;
358     int mSampledTimeoutPollLatencySum;
359 #endif
360 
361     // This state is only used privately by pollOnce and does not require a lock since
362     // it runs on a single thread.
363     Vector<Response> mResponses;
364     size_t mResponseIndex;
365     nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
366 
367     int pollInner(int timeoutMillis);
368     void awoken();
369     void pushResponse(int events, const Request& request);
370 
371     static void initTLSKey();
372     static void threadDestructor(void *st);
373 };
374 
375 } // namespace android
376 
377 #endif // UTILS_LOOPER_H
378