| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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> | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 23 | #include <utils/Timers.h> | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 24 |  | 
 | 25 | #include <android/looper.h> | 
 | 26 |  | 
| Jeff Brown | dc4c5bf | 2010-10-07 16:17:57 -0700 | [diff] [blame] | 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. | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 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 |  | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 39 | /* | 
 | 40 |  * Declare a concrete type for the NDK's looper forward declaration. | 
 | 41 |  */ | 
 | 42 | struct ALooper { | 
 | 43 | }; | 
 | 44 |  | 
 | 45 | namespace android { | 
 | 46 |  | 
 | 47 | /** | 
| Jeff Brown | 80f3e7c | 2011-03-02 14:41:58 -0800 | [diff] [blame] | 48 |  * A message that can be posted to a Looper. | 
 | 49 |  */ | 
 | 50 | struct Message { | 
 | 51 |     Message() : what(0) { } | 
 | 52 |     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: | 
 | 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 | /** | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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 |      */ | 
| Jeff Brown | b0619e8 | 2010-09-16 18:28:12 -0700 | [diff] [blame] | 144 |     int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData); | 
 | 145 |     inline int pollOnce(int timeoutMillis) { | 
 | 146 |         return pollOnce(timeoutMillis, NULL, NULL, NULL); | 
 | 147 |     } | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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 |      */ | 
| Jeff Brown | b0619e8 | 2010-09-16 18:28:12 -0700 | [diff] [blame] | 154 |     int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData); | 
 | 155 |     inline int pollAll(int timeoutMillis) { | 
 | 156 |         return pollAll(timeoutMillis, NULL, NULL, NULL); | 
 | 157 |     } | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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 |      */ | 
| Jeff Brown | b0619e8 | 2010-09-16 18:28:12 -0700 | [diff] [blame] | 193 |     int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data); | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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 |     /** | 
| Jeff Brown | 80f3e7c | 2011-03-02 14:41:58 -0800 | [diff] [blame] | 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 |     /** | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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 |  | 
| Jeff Brown | 80f3e7c | 2011-03-02 14:41:58 -0800 | [diff] [blame] | 295 |     struct MessageEnvelope { | 
 | 296 |         MessageEnvelope() : uptime(0) { } | 
 | 297 |  | 
 | 298 |         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 |  | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 307 |     const bool mAllowNonCallbacks; // immutable | 
 | 308 |  | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 309 |     int mWakeReadPipeFd;  // immutable | 
 | 310 |     int mWakeWritePipeFd; // immutable | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 311 |     Mutex mLock; | 
 | 312 |  | 
| Jeff Brown | 80f3e7c | 2011-03-02 14:41:58 -0800 | [diff] [blame] | 313 |     Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock | 
 | 314 |     bool mSendingMessage; // guarded by mLock | 
 | 315 |  | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 316 | #ifdef LOOPER_USES_EPOLL | 
 | 317 |     int mEpollFd; // immutable | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 318 |  | 
 | 319 |     // Locked list of file descriptor monitoring requests. | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 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 | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 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; | 
| Jeff Brown | 80f3e7c | 2011-03-02 14:41:58 -0800 | [diff] [blame] | 365 |     nsecs_t mNextMessageUptime; // set to LLONG_MAX when none | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 366 |  | 
 | 367 |     int pollInner(int timeoutMillis); | 
| Jeff Brown | 54e1cda | 2010-10-05 15:35:37 -0700 | [diff] [blame] | 368 |     void awoken(); | 
 | 369 |     void pushResponse(int events, const Request& request); | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 370 |  | 
| Jeff Brown | 61a25b2 | 2010-09-21 15:11:18 -0700 | [diff] [blame] | 371 |     static void initTLSKey(); | 
| Jeff Brown | 59abe7e | 2010-09-13 23:17:30 -0700 | [diff] [blame] | 372 |     static void threadDestructor(void *st); | 
 | 373 | }; | 
 | 374 |  | 
 | 375 | } // namespace android | 
 | 376 |  | 
 | 377 | #endif // UTILS_LOOPER_H |