| /* | 
 |  * Copyright (C) 2010 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef UTILS_POLL_LOOP_H | 
 | #define UTILS_POLL_LOOP_H | 
 |  | 
 | #include <utils/Vector.h> | 
 | #include <utils/threads.h> | 
 |  | 
 | #include <sys/poll.h> | 
 |  | 
 | #include <android/looper.h> | 
 |  | 
 | struct ALooper : public android::RefBase { | 
 | protected: | 
 |     virtual ~ALooper() { } | 
 |  | 
 | public: | 
 |     ALooper() { } | 
 | }; | 
 |  | 
 | namespace android { | 
 |  | 
 | /** | 
 |  * A basic file descriptor polling loop based on poll() with callbacks. | 
 |  */ | 
 | class PollLoop : public ALooper { | 
 | protected: | 
 |     virtual ~PollLoop(); | 
 |  | 
 | public: | 
 |     PollLoop(bool allowNonCallbacks); | 
 |  | 
 |     /** | 
 |      * A callback that it to be invoked when an event occurs on a file descriptor. | 
 |      * Specifies the events that were triggered and the user data provided when the | 
 |      * callback was set. | 
 |      * | 
 |      * Returns true if the callback should be kept, false if it should be removed automatically | 
 |      * after the callback returns. | 
 |      */ | 
 |     typedef bool (*Callback)(int fd, int events, void* data); | 
 |  | 
 |     enum { | 
 |         POLL_CALLBACK = ALOOPER_POLL_CALLBACK, | 
 |         POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT, | 
 |         POLL_ERROR = ALOOPER_POLL_ERROR, | 
 |     }; | 
 |      | 
 |     /** | 
 |      * Performs a single call to poll() with optional timeout in milliseconds. | 
 |      * Invokes callbacks for all file descriptors on which an event occurred. | 
 |      * | 
 |      * If the timeout is zero, returns immediately without blocking. | 
 |      * If the timeout is negative, waits indefinitely until awoken. | 
 |      * | 
 |      * Returns ALOOPER_POLL_CALLBACK if a callback was invoked. | 
 |      * | 
 |      * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given | 
 |      * timeout expired. | 
 |      * | 
 |      * Returns ALOPER_POLL_ERROR if an error occurred. | 
 |      * | 
 |      * Returns a value >= 0 containing a file descriptor if it has data | 
 |      * and it has no callback function (requiring the caller here to handle it). | 
 |      * In this (and only this) case outEvents and outData will contain the poll | 
 |      * events and data associated with the fd. | 
 |      * | 
 |      * This method must only be called on the thread owning the PollLoop. | 
 |      * This method blocks until either a file descriptor is signalled, a timeout occurs, | 
 |      * or wake() is called. | 
 |      * This method does not return until it has finished invoking the appropriate callbacks | 
 |      * for all file descriptors that were signalled. | 
 |      */ | 
 |     int32_t pollOnce(int timeoutMillis, int* outEvents = NULL, void** outData = NULL); | 
 |  | 
 |     /** | 
 |      * Wakes the loop asynchronously. | 
 |      * | 
 |      * This method can be called on any thread. | 
 |      * This method returns immediately. | 
 |      */ | 
 |     void wake(); | 
 |  | 
 |     /** | 
 |      * Control whether this PollLoop instance allows using IDs instead | 
 |      * of callbacks. | 
 |      */ | 
 |     bool getAllowNonCallbacks() const; | 
 |      | 
 |     /** | 
 |      * Sets the callback for a file descriptor, replacing the existing one, if any. | 
 |      * It is an error to call this method with events == 0 or callback == NULL. | 
 |      * | 
 |      * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events | 
 |      * even if it is not explicitly requested when registered. | 
 |      * | 
 |      * This method can be called on any thread. | 
 |      * This method may block briefly if it needs to wake the poll loop. | 
 |      */ | 
 |     void setCallback(int fd, int events, Callback callback, void* data = NULL); | 
 |  | 
 |     /** | 
 |      * Like setCallback(), but for the NDK callback function. | 
 |      */ | 
 |     void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, | 
 |             void* data); | 
 |      | 
 |     /** | 
 |      * Removes the callback for a file descriptor, if one exists. | 
 |      * | 
 |      * When this method returns, it is safe to close the file descriptor since the poll loop | 
 |      * will no longer have a reference to it.  However, it is possible for the callback to | 
 |      * already be running or for it to run one last time if the file descriptor was already | 
 |      * signalled.  Calling code is responsible for ensuring that this case is safely handled. | 
 |      * For example, if the callback takes care of removing itself during its own execution either | 
 |      * by returning false or calling this method, then it can be guaranteed to not be invoked | 
 |      * again at any later time unless registered anew. | 
 |      * | 
 |      * This method can be called on any thread. | 
 |      * This method may block briefly if it needs to wake the poll loop. | 
 |      * | 
 |      * Returns true if a callback was actually removed, false if none was registered. | 
 |      */ | 
 |     bool removeCallback(int fd); | 
 |  | 
 |     /** | 
 |      * Set the given PollLoop to be associated with the | 
 |      * calling thread.  There must be a 1:1 relationship between | 
 |      * PollLoop and thread. | 
 |      */ | 
 |     static void setForThread(const sp<PollLoop>& pollLoop); | 
 |      | 
 |     /** | 
 |      * Return the PollLoop associated with the calling thread. | 
 |      */ | 
 |     static sp<PollLoop> getForThread(); | 
 |      | 
 | private: | 
 |     struct RequestedCallback { | 
 |         Callback callback; | 
 |         ALooper_callbackFunc* looperCallback; | 
 |         void* data; | 
 |     }; | 
 |  | 
 |     struct PendingCallback { | 
 |         int fd; | 
 |         int events; | 
 |         Callback callback; | 
 |         ALooper_callbackFunc* looperCallback; | 
 |         void* data; | 
 |     }; | 
 |      | 
 |     const bool mAllowNonCallbacks; | 
 |      | 
 |     Mutex mLock; | 
 |     bool mPolling; | 
 |     uint32_t mWaiters; | 
 |     Condition mAwake; | 
 |     Condition mResume; | 
 |  | 
 |     int mWakeReadPipeFd; | 
 |     int mWakeWritePipeFd; | 
 |  | 
 |     Vector<struct pollfd> mRequestedFds; | 
 |     Vector<RequestedCallback> mRequestedCallbacks; | 
 |  | 
 |     Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce | 
 |     Vector<PendingCallback> mPendingFds;       // used privately by pollOnce | 
 |     size_t mPendingFdsPos; | 
 |      | 
 |     void openWakePipe(); | 
 |     void closeWakePipe(); | 
 |  | 
 |     void setCallbackCommon(int fd, int events, Callback callback, | 
 |             ALooper_callbackFunc* looperCallback, void* data); | 
 |     ssize_t getRequestIndexLocked(int fd); | 
 |     void wakeAndLock(); | 
 |     static void threadDestructor(void *st); | 
 | }; | 
 |  | 
 | } // namespace android | 
 |  | 
 | #endif // UTILS_POLL_LOOP_H |