/* * Copyright (C) 2009 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 TIMED_EVENT_QUEUE_H_ #define TIMED_EVENT_QUEUE_H_ #include #include #include #include #include namespace android { struct TimedEventQueue { typedef int32_t event_id; struct Event : public RefBase { Event() : mEventID(0) { } virtual ~Event() {} event_id eventID() { return mEventID; } protected: virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0; private: friend class TimedEventQueue; event_id mEventID; void setEventID(event_id id) { mEventID = id; } Event(const Event &); Event &operator=(const Event &); }; class PMDeathRecipient : public IBinder::DeathRecipient { public: PMDeathRecipient(TimedEventQueue *queue) : mQueue(queue) {} virtual ~PMDeathRecipient() {} // IBinder::DeathRecipient virtual void binderDied(const wp& who); private: PMDeathRecipient(const PMDeathRecipient&); PMDeathRecipient& operator = (const PMDeathRecipient&); TimedEventQueue *mQueue; }; TimedEventQueue(); ~TimedEventQueue(); // Start executing the event loop. void start(); // Stop executing the event loop, if flush is false, any pending // events are discarded, otherwise the queue will stop (and this call // return) once all pending events have been handled. void stop(bool flush = false); // Posts an event to the front of the queue (after all events that // have previously been posted to the front but before timed events). event_id postEvent(const sp &event); event_id postEventToBack(const sp &event); // It is an error to post an event with a negative delay. event_id postEventWithDelay(const sp &event, int64_t delay_us); // If the event is to be posted at a time that has already passed, // it will fire as soon as possible. event_id postTimedEvent(const sp &event, int64_t realtime_us); // Returns true iff event is currently in the queue and has been // successfully cancelled. In this case the event will have been // removed from the queue and won't fire. bool cancelEvent(event_id id); // Cancel any pending event that satisfies the predicate. // If stopAfterFirstMatch is true, only cancels the first event // satisfying the predicate (if any). void cancelEvents( bool (*predicate)(void *cookie, const sp &event), void *cookie, bool stopAfterFirstMatch = false); static int64_t getRealTimeUs(); void clearPowerManager(); private: struct QueueItem { sp event; int64_t realtime_us; bool has_wakelock; }; struct StopEvent : public TimedEventQueue::Event { virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { queue->mStopped = true; } }; pthread_t mThread; List mQueue; Mutex mLock; Condition mQueueNotEmptyCondition; Condition mQueueHeadChangedCondition; event_id mNextEventID; bool mRunning; bool mStopped; sp mPowerManager; sp mWakeLockToken; const sp mDeathRecipient; uint32_t mWakeLockCount; static void *ThreadWrapper(void *me); void threadEntry(); sp removeEventFromQueue_l(event_id id, bool *wakeLocked); void acquireWakeLock_l(); void releaseWakeLock_l(bool force = false); TimedEventQueue(const TimedEventQueue &); TimedEventQueue &operator=(const TimedEventQueue &); }; } // namespace android #endif // TIMED_EVENT_QUEUE_H_