am a35f1c63: Merge change Ib64ea2dd into eclair-mr2

Merge commit 'a35f1c63a67df0832d9b3f1aed3e2376367d4398' into eclair-mr2-plus-aosp

* commit 'a35f1c63a67df0832d9b3f1aed3e2376367d4398':
  Improvements to TimedEventQueue.
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index dd8005c..fa68771 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -31,7 +31,8 @@
 namespace android {
 
 TimedEventQueue::TimedEventQueue()
-    : mRunning(false),
+    : mNextEventID(1),
+      mRunning(false),
       mStopped(false) {
 }
 
@@ -76,26 +77,29 @@
     mRunning = false;
 }
 
-void TimedEventQueue::postEvent(const sp<Event> &event) {
+TimedEventQueue::event_id TimedEventQueue::postEvent(const sp<Event> &event) {
     // Reserve an earlier timeslot an INT64_MIN to be able to post
     // the StopEvent to the absolute head of the queue.
-    postTimedEvent(event, INT64_MIN + 1);
+    return postTimedEvent(event, INT64_MIN + 1);
 }
 
-void TimedEventQueue::postEventToBack(const sp<Event> &event) {
-    postTimedEvent(event, INT64_MAX);
+TimedEventQueue::event_id TimedEventQueue::postEventToBack(
+        const sp<Event> &event) {
+    return postTimedEvent(event, INT64_MAX);
 }
 
-void TimedEventQueue::postEventWithDelay(
+TimedEventQueue::event_id TimedEventQueue::postEventWithDelay(
         const sp<Event> &event, int64_t delay_us) {
     CHECK(delay_us >= 0);
-    postTimedEvent(event, getRealTimeUs() + delay_us);
+    return postTimedEvent(event, getRealTimeUs() + delay_us);
 }
 
-void TimedEventQueue::postTimedEvent(
+TimedEventQueue::event_id TimedEventQueue::postTimedEvent(
         const sp<Event> &event, int64_t realtime_us) {
     Mutex::Autolock autoLock(mLock);
 
+    event->setEventID(mNextEventID++);
+
     List<QueueItem>::iterator it = mQueue.begin();
     while (it != mQueue.end() && realtime_us >= (*it).realtime_us) {
         ++it;
@@ -112,29 +116,60 @@
     mQueue.insert(it, item);
 
     mQueueNotEmptyCondition.signal();
+
+    return event->eventID();
 }
 
-bool TimedEventQueue::cancelEvent(const sp<Event> &event) {
-    Mutex::Autolock autoLock(mLock);
+static bool MatchesEventID(
+        void *cookie, const sp<TimedEventQueue::Event> &event) {
+    TimedEventQueue::event_id *id =
+        static_cast<TimedEventQueue::event_id *>(cookie);
 
-    List<QueueItem>::iterator it = mQueue.begin();
-    while (it != mQueue.end() && (*it).event != event) {
-        ++it;
-    }
-
-    if (it == mQueue.end()) {
+    if (event->eventID() != *id) {
         return false;
     }
 
-    if (it == mQueue.begin()) {
-        mQueueHeadChangedCondition.signal();
-    }
-
-    mQueue.erase(it);
+    *id = 0;
 
     return true;
 }
 
+bool TimedEventQueue::cancelEvent(event_id id) {
+    CHECK(id != 0);
+
+    cancelEvents(&MatchesEventID, &id, true /* stopAfterFirstMatch */);
+
+    // if MatchesEventID found a match, it will have set id to 0
+    // (which is not a valid event_id).
+
+    return id == 0;
+}
+
+void TimedEventQueue::cancelEvents(
+        bool (*predicate)(void *cookie, const sp<Event> &event),
+        void *cookie,
+        bool stopAfterFirstMatch) {
+    Mutex::Autolock autoLock(mLock);
+
+    List<QueueItem>::iterator it = mQueue.begin();
+    while (it != mQueue.end()) {
+        if (!(*predicate)(cookie, (*it).event)) {
+            ++it;
+            continue;
+        }
+
+        if (it == mQueue.begin()) {
+            mQueueHeadChangedCondition.signal();
+        }
+
+        it = mQueue.erase(it);
+
+        if (stopAfterFirstMatch) {
+            return;
+        }
+    }
+}
+
 // static
 int64_t TimedEventQueue::getRealTimeUs() {
     struct timeval tv;
diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h
index a264421..21eade37 100644
--- a/media/libstagefright/include/TimedEventQueue.h
+++ b/media/libstagefright/include/TimedEventQueue.h
@@ -28,16 +28,31 @@
 
 struct TimedEventQueue {
 
+    typedef int32_t event_id;
+
     struct Event : public RefBase {
-        Event() {}
+        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 &);
     };
@@ -55,21 +70,29 @@
 
     // Posts an event to the front of the queue (after all events that
     // have previously been posted to the front but before timed events).
-    void postEvent(const sp<Event> &event);
+    event_id postEvent(const sp<Event> &event);
 
-    void postEventToBack(const sp<Event> &event);
+    event_id postEventToBack(const sp<Event> &event);
 
     // It is an error to post an event with a negative delay.
-    void postEventWithDelay(const sp<Event> &event, int64_t delay_us);
+    event_id postEventWithDelay(const sp<Event> &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.
-    void postTimedEvent(const sp<Event> &event, int64_t realtime_us);
+    event_id postTimedEvent(const sp<Event> &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(const sp<Event> &event);
+    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> &event),
+            void *cookie,
+            bool stopAfterFirstMatch = false);
 
     static int64_t getRealTimeUs();
 
@@ -90,6 +113,7 @@
     Mutex mLock;
     Condition mQueueNotEmptyCondition;
     Condition mQueueHeadChangedCondition;
+    event_id mNextEventID;
 
     bool mRunning;
     bool mStopped;