Loading include/gui/SensorEventQueue.h +3 −3 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ namespace android { class ISensorEventConnection; class Sensor; class PollLoop; class Looper; // ---------------------------------------------------------------------------- Loading @@ -69,11 +69,11 @@ public: status_t disableSensor(int32_t handle) const; private: sp<PollLoop> getPollLoop() const; sp<Looper> getLooper() const; sp<ISensorEventConnection> mSensorEventConnection; sp<SensorChannel> mSensorChannel; mutable Mutex mLock; mutable sp<PollLoop> mPollLoop; mutable sp<Looper> mLooper; }; // ---------------------------------------------------------------------------- Loading include/ui/InputDispatcher.h +4 −4 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/PollLoop.h> #include <utils/Looper.h> #include <utils/Pool.h> #include <stddef.h> Loading Loading @@ -826,7 +826,7 @@ private: Mutex mLock; Allocator mAllocator; sp<PollLoop> mPollLoop; sp<Looper> mLooper; EventEntry* mPendingEvent; Queue<EventEntry> mInboundQueue; Loading @@ -837,7 +837,7 @@ private: void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime); // Enqueues an inbound event. Returns true if mPollLoop->wake() should be called. // Enqueues an inbound event. Returns true if mLooper->wake() should be called. bool enqueueInboundEventLocked(EventEntry* entry); // App switch latency optimization. Loading Loading @@ -1010,7 +1010,7 @@ private: void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool broken); void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain); static bool handleReceiveCallback(int receiveFd, int events, void* data); static int handleReceiveCallback(int receiveFd, int events, void* data); // Preempting input dispatch. bool preemptInputDispatchInnerLocked(); Loading include/ui/InputTransport.h +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ #include <semaphore.h> #include <ui/Input.h> #include <utils/Errors.h> #include <utils/PollLoop.h> #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> Loading include/utils/PollLoop.h→include/utils/Looper.h +210 −0 Original line number Diff line number Diff line Loading @@ -14,81 +14,88 @@ * limitations under the License. */ #ifndef UTILS_POLL_LOOP_H #define UTILS_POLL_LOOP_H #ifndef UTILS_LOOPER_H #define UTILS_LOOPER_H #include <utils/Vector.h> #include <utils/threads.h> #include <sys/poll.h> #include <utils/RefBase.h> #include <utils/KeyedVector.h> #include <android/looper.h> struct ALooper : public android::RefBase { protected: virtual ~ALooper() { } public: ALooper() { } /* * Declare a concrete type for the NDK's looper forward declaration. */ struct ALooper { }; namespace android { /** * A basic file descriptor polling loop based on poll() with callbacks. * A polling loop that supports monitoring file descriptor events, optionally * using callbacks. The implementation uses epoll() internally. * * A looper can be associated with a thread although there is no requirement that it must be. */ class PollLoop : public ALooper { class Looper : public ALooper, public RefBase { protected: virtual ~PollLoop(); virtual ~Looper(); 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. * Creates a looper. * * Returns true if the callback should be kept, false if it should be removed automatically * after the callback returns. * If allowNonCallbaks is true, the looper will allow file descriptors to be * registered without associated callbacks. This assumes that the caller of * pollOnce() is prepared to handle callback-less events itself. */ typedef bool (*Callback)(int fd, int events, void* data); Looper(bool allowNonCallbacks); enum { POLL_CALLBACK = ALOOPER_POLL_CALLBACK, POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT, POLL_ERROR = ALOOPER_POLL_ERROR, }; /** * Returns whether this looper instance allows the registration of file descriptors * using identifiers instead of callbacks. */ bool getAllowNonCallbacks() const; /** * Performs a single call to poll() with optional timeout in milliseconds. * Waits for events to be available, 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. * If the timeout is negative, waits indefinitely until an event appears. * * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before * the timeout expired and no callbacks were invoked and no other file * descriptors were ready. * * Returns ALOOPER_POLL_CALLBACK if a callback was invoked. * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. * * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given * timeout expired. * * Returns ALOPER_POLL_ERROR if an error occurred. * Returns ALOOPER_POLL_ERROR if an error occurred. * * Returns a value >= 0 containing a file descriptor if it has data * Returns a value >= 0 containing an identifier if its file descriptor 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. * In this (and only this) case outFd, outEvents and outData will contain the poll * events and data associated with the fd, otherwise they will be set to NULL. * * 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); int pollOnce(int timeoutMillis, int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); /** * Like pollOnce(), but performs all pending callbacks until all * data has been consumed or a file descriptor is available with no callback. * This function will never return ALOOPER_POLL_CALLBACK. */ int pollAll(int timeoutMillis, int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); /** * Wakes the loop asynchronously. * Wakes the poll asynchronously. * * This method can be called on any thread. * This method returns immediately. Loading @@ -96,124 +103,108 @@ public: 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. * Adds a new file descriptor to be polled by the looper. * If the same file descriptor was previously added, it is replaced. * * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events * even if it is not explicitly requested when registered. * "fd" is the file descriptor to be added. * "ident" is an identifier for this event, which is returned from ALooper_pollOnce(). * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback. * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT. * "callback" is the function to call when there is an event on the file descriptor. * "data" is a private data pointer to supply to the callback. * * There are two main uses of this function: * * (1) If "callback" is non-NULL, then this function will be called when there is * data on the file descriptor. It should execute any events it has pending, * appropriately reading from the file descriptor. The 'ident' is ignored in this case. * * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce * when its file descriptor has data available, requiring the caller to take * care of processing it. * * Returns 1 if the file descriptor was added, 0 if the arguments were invalid. * * 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 ident, int events, Callback callback, void* data = NULL); /** * Convenience for above setCallback when ident is not used. In this case * the ident is set to POLL_CALLBACK. */ void setCallback(int fd, int events, Callback callback, void* data = NULL); /** * Like setCallback(), but for the NDK callback function. * This method may block briefly if it needs to wake the poll. */ void setLooperCallback(int fd, int ident, int events, ALooper_callbackFunc* callback, void* data); int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data = NULL); /** * Removes the callback for a file descriptor, if one exists. * Removes a previously added file descriptor from the looper. * * When this method returns, it is safe to close the file descriptor since the poll loop * When this method returns, it is safe to close the file descriptor since the looper * 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 * by returning 0 or by calling this method, then it can be guaranteed to not be invoked * again at any later time unless registered anew. * * Returns 1 if the file descriptor was removed, 0 if none was previously registered. * * This method can be called on any thread. * This method may block briefly if it needs to wake the poll loop. * This method may block briefly if it needs to wake the poll. */ int removeFd(int fd); /** * Prepares a looper associated with the calling thread, and returns it. * If the thread already has a looper, it is returned. Otherwise, a new * one is created, associated with the thread, and returned. * * Returns true if a callback was actually removed, false if none was registered. * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0. */ bool removeCallback(int fd); static sp<Looper> prepare(int opts); /** * Set the given PollLoop to be associated with the * calling thread. There must be a 1:1 relationship between * PollLoop and thread. * Sets the given looper to be associated with the calling thread. * If another looper is already associated with the thread, it is replaced. * * If "looper" is NULL, removes the currently associated looper. */ static void setForThread(const sp<PollLoop>& pollLoop); static void setForThread(const sp<Looper>& looper); /** * Return the PollLoop associated with the calling thread. * Returns the looper associated with the calling thread, or NULL if * there is not one. */ static sp<PollLoop> getForThread(); static sp<Looper> getForThread(); private: struct RequestedCallback { Callback callback; ALooper_callbackFunc* looperCallback; struct Request { int fd; int ident; ALooper_callbackFunc callback; void* data; }; struct PendingCallback { int fd; int ident; struct Response { int events; Callback callback; ALooper_callbackFunc* looperCallback; void* data; Request request; }; const bool mAllowNonCallbacks; // immutable int mEpollFd; // immutable int mWakeReadPipeFd; // immutable int mWakeWritePipeFd; // immutable // The lock guards state used to track whether there is a poll() in progress and whether // there are any other threads waiting in wakeAndLock(). The condition variables // are used to transfer control among these threads such that all waiters are // serviced before a new poll can begin. // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake // until mPolling becomes false, then decrements mWaiters again. // The poll() method blocks on mResume until mWaiters becomes 0, then sets // mPolling to true, blocks until the poll completes, then resets mPolling to false // and signals mResume if there are waiters. // Locked list of file descriptor monitoring requests. Mutex mLock; bool mPolling; // guarded by mLock uint32_t mWaiters; // guarded by mLock Condition mAwake; // guarded by mLock Condition mResume; // guarded by mLock // The next two vectors are only mutated when mPolling is false since they must // not be changed while the poll() system call is in progress. To mutate these // vectors, the poll() must first be awoken then the lock acquired. Vector<struct pollfd> mRequestedFds; Vector<RequestedCallback> mRequestedCallbacks; KeyedVector<int, Request> mRequests; // This state is only used privately by pollOnce and does not require a lock since // it runs on a single thread. Vector<PendingCallback> mPendingCallbacks; Vector<PendingCallback> mPendingFds; size_t mPendingFdsPos; Vector<Response> mResponses; size_t mResponseIndex; void openWakePipe(); void closeWakePipe(); int pollInner(int timeoutMillis); void setCallbackCommon(int fd, int ident, 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 #endif // UTILS_LOOPER_H libs/gui/SensorEventQueue.cpp +11 −11 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/PollLoop.h> #include <utils/Looper.h> #include <gui/Sensor.h> #include <gui/SensorChannel.h> Loading Loading @@ -81,28 +81,28 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) return size; } sp<PollLoop> SensorEventQueue::getPollLoop() const sp<Looper> SensorEventQueue::getLooper() const { Mutex::Autolock _l(mLock); if (mPollLoop == 0) { mPollLoop = new PollLoop(true); mPollLoop->setCallback(getFd(), getFd(), POLLIN, NULL, NULL); if (mLooper == 0) { mLooper = new Looper(true); mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); } return mPollLoop; return mLooper; } status_t SensorEventQueue::waitForEvent() const { const int fd = getFd(); sp<PollLoop> pollLoop(getPollLoop()); int32_t result = pollLoop->pollOnce(-1, NULL, NULL); return (result == fd) ? NO_ERROR : -1; sp<Looper> looper(getLooper()); int32_t result = looper->pollOnce(-1); return (result == fd) ? status_t(NO_ERROR) : status_t(-1); } status_t SensorEventQueue::wake() const { sp<PollLoop> pollLoop(getPollLoop()); pollLoop->wake(); sp<Looper> looper(getLooper()); looper->wake(); return NO_ERROR; } Loading Loading
include/gui/SensorEventQueue.h +3 −3 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ namespace android { class ISensorEventConnection; class Sensor; class PollLoop; class Looper; // ---------------------------------------------------------------------------- Loading @@ -69,11 +69,11 @@ public: status_t disableSensor(int32_t handle) const; private: sp<PollLoop> getPollLoop() const; sp<Looper> getLooper() const; sp<ISensorEventConnection> mSensorEventConnection; sp<SensorChannel> mSensorChannel; mutable Mutex mLock; mutable sp<PollLoop> mPollLoop; mutable sp<Looper> mLooper; }; // ---------------------------------------------------------------------------- Loading
include/ui/InputDispatcher.h +4 −4 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/PollLoop.h> #include <utils/Looper.h> #include <utils/Pool.h> #include <stddef.h> Loading Loading @@ -826,7 +826,7 @@ private: Mutex mLock; Allocator mAllocator; sp<PollLoop> mPollLoop; sp<Looper> mLooper; EventEntry* mPendingEvent; Queue<EventEntry> mInboundQueue; Loading @@ -837,7 +837,7 @@ private: void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime); // Enqueues an inbound event. Returns true if mPollLoop->wake() should be called. // Enqueues an inbound event. Returns true if mLooper->wake() should be called. bool enqueueInboundEventLocked(EventEntry* entry); // App switch latency optimization. Loading Loading @@ -1010,7 +1010,7 @@ private: void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool broken); void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain); static bool handleReceiveCallback(int receiveFd, int events, void* data); static int handleReceiveCallback(int receiveFd, int events, void* data); // Preempting input dispatch. bool preemptInputDispatchInnerLocked(); Loading
include/ui/InputTransport.h +0 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ #include <semaphore.h> #include <ui/Input.h> #include <utils/Errors.h> #include <utils/PollLoop.h> #include <utils/Timers.h> #include <utils/RefBase.h> #include <utils/String8.h> Loading
include/utils/PollLoop.h→include/utils/Looper.h +210 −0 Original line number Diff line number Diff line Loading @@ -14,81 +14,88 @@ * limitations under the License. */ #ifndef UTILS_POLL_LOOP_H #define UTILS_POLL_LOOP_H #ifndef UTILS_LOOPER_H #define UTILS_LOOPER_H #include <utils/Vector.h> #include <utils/threads.h> #include <sys/poll.h> #include <utils/RefBase.h> #include <utils/KeyedVector.h> #include <android/looper.h> struct ALooper : public android::RefBase { protected: virtual ~ALooper() { } public: ALooper() { } /* * Declare a concrete type for the NDK's looper forward declaration. */ struct ALooper { }; namespace android { /** * A basic file descriptor polling loop based on poll() with callbacks. * A polling loop that supports monitoring file descriptor events, optionally * using callbacks. The implementation uses epoll() internally. * * A looper can be associated with a thread although there is no requirement that it must be. */ class PollLoop : public ALooper { class Looper : public ALooper, public RefBase { protected: virtual ~PollLoop(); virtual ~Looper(); 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. * Creates a looper. * * Returns true if the callback should be kept, false if it should be removed automatically * after the callback returns. * If allowNonCallbaks is true, the looper will allow file descriptors to be * registered without associated callbacks. This assumes that the caller of * pollOnce() is prepared to handle callback-less events itself. */ typedef bool (*Callback)(int fd, int events, void* data); Looper(bool allowNonCallbacks); enum { POLL_CALLBACK = ALOOPER_POLL_CALLBACK, POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT, POLL_ERROR = ALOOPER_POLL_ERROR, }; /** * Returns whether this looper instance allows the registration of file descriptors * using identifiers instead of callbacks. */ bool getAllowNonCallbacks() const; /** * Performs a single call to poll() with optional timeout in milliseconds. * Waits for events to be available, 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. * If the timeout is negative, waits indefinitely until an event appears. * * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before * the timeout expired and no callbacks were invoked and no other file * descriptors were ready. * * Returns ALOOPER_POLL_CALLBACK if a callback was invoked. * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. * * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given * timeout expired. * * Returns ALOPER_POLL_ERROR if an error occurred. * Returns ALOOPER_POLL_ERROR if an error occurred. * * Returns a value >= 0 containing a file descriptor if it has data * Returns a value >= 0 containing an identifier if its file descriptor 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. * In this (and only this) case outFd, outEvents and outData will contain the poll * events and data associated with the fd, otherwise they will be set to NULL. * * 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); int pollOnce(int timeoutMillis, int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); /** * Like pollOnce(), but performs all pending callbacks until all * data has been consumed or a file descriptor is available with no callback. * This function will never return ALOOPER_POLL_CALLBACK. */ int pollAll(int timeoutMillis, int* outFd = NULL, int* outEvents = NULL, void** outData = NULL); /** * Wakes the loop asynchronously. * Wakes the poll asynchronously. * * This method can be called on any thread. * This method returns immediately. Loading @@ -96,124 +103,108 @@ public: 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. * Adds a new file descriptor to be polled by the looper. * If the same file descriptor was previously added, it is replaced. * * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events * even if it is not explicitly requested when registered. * "fd" is the file descriptor to be added. * "ident" is an identifier for this event, which is returned from ALooper_pollOnce(). * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback. * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT. * "callback" is the function to call when there is an event on the file descriptor. * "data" is a private data pointer to supply to the callback. * * There are two main uses of this function: * * (1) If "callback" is non-NULL, then this function will be called when there is * data on the file descriptor. It should execute any events it has pending, * appropriately reading from the file descriptor. The 'ident' is ignored in this case. * * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce * when its file descriptor has data available, requiring the caller to take * care of processing it. * * Returns 1 if the file descriptor was added, 0 if the arguments were invalid. * * 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 ident, int events, Callback callback, void* data = NULL); /** * Convenience for above setCallback when ident is not used. In this case * the ident is set to POLL_CALLBACK. */ void setCallback(int fd, int events, Callback callback, void* data = NULL); /** * Like setCallback(), but for the NDK callback function. * This method may block briefly if it needs to wake the poll. */ void setLooperCallback(int fd, int ident, int events, ALooper_callbackFunc* callback, void* data); int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data = NULL); /** * Removes the callback for a file descriptor, if one exists. * Removes a previously added file descriptor from the looper. * * When this method returns, it is safe to close the file descriptor since the poll loop * When this method returns, it is safe to close the file descriptor since the looper * 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 * by returning 0 or by calling this method, then it can be guaranteed to not be invoked * again at any later time unless registered anew. * * Returns 1 if the file descriptor was removed, 0 if none was previously registered. * * This method can be called on any thread. * This method may block briefly if it needs to wake the poll loop. * This method may block briefly if it needs to wake the poll. */ int removeFd(int fd); /** * Prepares a looper associated with the calling thread, and returns it. * If the thread already has a looper, it is returned. Otherwise, a new * one is created, associated with the thread, and returned. * * Returns true if a callback was actually removed, false if none was registered. * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0. */ bool removeCallback(int fd); static sp<Looper> prepare(int opts); /** * Set the given PollLoop to be associated with the * calling thread. There must be a 1:1 relationship between * PollLoop and thread. * Sets the given looper to be associated with the calling thread. * If another looper is already associated with the thread, it is replaced. * * If "looper" is NULL, removes the currently associated looper. */ static void setForThread(const sp<PollLoop>& pollLoop); static void setForThread(const sp<Looper>& looper); /** * Return the PollLoop associated with the calling thread. * Returns the looper associated with the calling thread, or NULL if * there is not one. */ static sp<PollLoop> getForThread(); static sp<Looper> getForThread(); private: struct RequestedCallback { Callback callback; ALooper_callbackFunc* looperCallback; struct Request { int fd; int ident; ALooper_callbackFunc callback; void* data; }; struct PendingCallback { int fd; int ident; struct Response { int events; Callback callback; ALooper_callbackFunc* looperCallback; void* data; Request request; }; const bool mAllowNonCallbacks; // immutable int mEpollFd; // immutable int mWakeReadPipeFd; // immutable int mWakeWritePipeFd; // immutable // The lock guards state used to track whether there is a poll() in progress and whether // there are any other threads waiting in wakeAndLock(). The condition variables // are used to transfer control among these threads such that all waiters are // serviced before a new poll can begin. // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake // until mPolling becomes false, then decrements mWaiters again. // The poll() method blocks on mResume until mWaiters becomes 0, then sets // mPolling to true, blocks until the poll completes, then resets mPolling to false // and signals mResume if there are waiters. // Locked list of file descriptor monitoring requests. Mutex mLock; bool mPolling; // guarded by mLock uint32_t mWaiters; // guarded by mLock Condition mAwake; // guarded by mLock Condition mResume; // guarded by mLock // The next two vectors are only mutated when mPolling is false since they must // not be changed while the poll() system call is in progress. To mutate these // vectors, the poll() must first be awoken then the lock acquired. Vector<struct pollfd> mRequestedFds; Vector<RequestedCallback> mRequestedCallbacks; KeyedVector<int, Request> mRequests; // This state is only used privately by pollOnce and does not require a lock since // it runs on a single thread. Vector<PendingCallback> mPendingCallbacks; Vector<PendingCallback> mPendingFds; size_t mPendingFdsPos; Vector<Response> mResponses; size_t mResponseIndex; void openWakePipe(); void closeWakePipe(); int pollInner(int timeoutMillis); void setCallbackCommon(int fd, int ident, 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 #endif // UTILS_LOOPER_H
libs/gui/SensorEventQueue.cpp +11 −11 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/PollLoop.h> #include <utils/Looper.h> #include <gui/Sensor.h> #include <gui/SensorChannel.h> Loading Loading @@ -81,28 +81,28 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) return size; } sp<PollLoop> SensorEventQueue::getPollLoop() const sp<Looper> SensorEventQueue::getLooper() const { Mutex::Autolock _l(mLock); if (mPollLoop == 0) { mPollLoop = new PollLoop(true); mPollLoop->setCallback(getFd(), getFd(), POLLIN, NULL, NULL); if (mLooper == 0) { mLooper = new Looper(true); mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); } return mPollLoop; return mLooper; } status_t SensorEventQueue::waitForEvent() const { const int fd = getFd(); sp<PollLoop> pollLoop(getPollLoop()); int32_t result = pollLoop->pollOnce(-1, NULL, NULL); return (result == fd) ? NO_ERROR : -1; sp<Looper> looper(getLooper()); int32_t result = looper->pollOnce(-1); return (result == fd) ? status_t(NO_ERROR) : status_t(-1); } status_t SensorEventQueue::wake() const { sp<PollLoop> pollLoop(getPollLoop()); pollLoop->wake(); sp<Looper> looper(getLooper()); looper->wake(); return NO_ERROR; } Loading