Merge "audioflinger: fix wake lock acquisition check" into klp-dev
diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp
index b3304b7..dd4ad08 100644
--- a/media/libeffects/proxy/EffectProxy.cpp
+++ b/media/libeffects/proxy/EffectProxy.cpp
@@ -30,9 +30,10 @@
 // This is a dummy proxy descriptor just to return to Factory during the initial
 // GetDescriptor call. Later in the factory, it is replaced with the
 // SW sub effect descriptor
+// proxy UUID af8da7e0-2ca1-11e3-b71d-0002a5d5c51b
 const effect_descriptor_t gProxyDescriptor = {
         EFFECT_UUID_INITIALIZER, // type
-        EFFECT_UUID_INITIALIZER, // uuid
+        {0xaf8da7e0, 0x2ca1, 0x11e3, 0xb71d, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }}, // uuid
         EFFECT_CONTROL_API_VERSION, //version of effect control API
         (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST |
          EFFECT_FLAG_VOLUME_CTRL), // effect capability flags
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 1f68b51..6a2a696 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -89,6 +89,7 @@
         libutils \
         libvorbisidec \
         libz \
+        libpowermanager
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 7e9c4bf..74c5905 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -31,17 +31,24 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <binder/IServiceManager.h>
+#include <powermanager/PowerManager.h>
 
 namespace android {
 
 TimedEventQueue::TimedEventQueue()
     : mNextEventID(1),
       mRunning(false),
-      mStopped(false) {
+      mStopped(false),
+      mDeathRecipient(new PMDeathRecipient(this)) {
 }
 
 TimedEventQueue::~TimedEventQueue() {
     stop();
+    if (mPowerManager != 0) {
+        sp<IBinder> binder = mPowerManager->asBinder();
+        binder->unlinkToDeath(mDeathRecipient);
+    }
 }
 
 void TimedEventQueue::start() {
@@ -76,6 +83,11 @@
     void *dummy;
     pthread_join(mThread, &dummy);
 
+    // some events may be left in the queue if we did not flush and the wake lock
+    // must be released.
+    if (!mQueue.empty()) {
+        releaseWakeLock_l();
+    }
     mQueue.clear();
 
     mRunning = false;
@@ -117,6 +129,9 @@
         mQueueHeadChangedCondition.signal();
     }
 
+    if (mQueue.empty()) {
+        acquireWakeLock_l();
+    }
     mQueue.insert(it, item);
 
     mQueueNotEmptyCondition.signal();
@@ -172,7 +187,9 @@
 
         (*it).event->setEventID(0);
         it = mQueue.erase(it);
-
+        if (mQueue.empty()) {
+            releaseWakeLock_l();
+        }
         if (stopAfterFirstMatch) {
             return;
         }
@@ -280,7 +297,9 @@
             event->setEventID(0);
 
             mQueue.erase(it);
-
+            if (mQueue.empty()) {
+                releaseWakeLock_l();
+            }
             return event;
         }
     }
@@ -290,5 +309,56 @@
     return NULL;
 }
 
+void TimedEventQueue::acquireWakeLock_l()
+{
+    if (mWakeLockToken != 0) {
+        return;
+    }
+    if (mPowerManager == 0) {
+        // use checkService() to avoid blocking if power service is not up yet
+        sp<IBinder> binder =
+            defaultServiceManager()->checkService(String16("power"));
+        if (binder == 0) {
+            ALOGW("cannot connect to the power manager service");
+        } else {
+            mPowerManager = interface_cast<IPowerManager>(binder);
+            binder->linkToDeath(mDeathRecipient);
+        }
+    }
+    if (mPowerManager != 0) {
+        sp<IBinder> binder = new BBinder();
+        status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+                                                         binder,
+                                                         String16("TimedEventQueue"),
+                                                         String16("media"));
+        if (status == NO_ERROR) {
+            mWakeLockToken = binder;
+        }
+    }
+}
+
+void TimedEventQueue::releaseWakeLock_l()
+{
+    if (mWakeLockToken == 0) {
+        return;
+    }
+    if (mPowerManager != 0) {
+        mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+    }
+    mWakeLockToken.clear();
+}
+
+void TimedEventQueue::clearPowerManager()
+{
+    Mutex::Autolock _l(mLock);
+    releaseWakeLock_l();
+    mPowerManager.clear();
+}
+
+void TimedEventQueue::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+    mQueue->clearPowerManager();
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h
index 11f844c..4e49c83 100644
--- a/media/libstagefright/include/TimedEventQueue.h
+++ b/media/libstagefright/include/TimedEventQueue.h
@@ -23,6 +23,7 @@
 #include <utils/List.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include <powermanager/IPowerManager.h>
 
 namespace android {
 
@@ -57,6 +58,21 @@
         Event &operator=(const Event &);
     };
 
+    class PMDeathRecipient : public IBinder::DeathRecipient {
+    public:
+                    PMDeathRecipient(TimedEventQueue *queue) : mQueue(queue) {}
+        virtual     ~PMDeathRecipient() {}
+
+        // IBinder::DeathRecipient
+        virtual     void        binderDied(const wp<IBinder>& who);
+
+    private:
+                    PMDeathRecipient(const PMDeathRecipient&);
+                    PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+                    TimedEventQueue *mQueue;
+    };
+
     TimedEventQueue();
     ~TimedEventQueue();
 
@@ -96,6 +112,8 @@
 
     static int64_t getRealTimeUs();
 
+    void clearPowerManager();
+
 private:
     struct QueueItem {
         sp<Event> event;
@@ -118,11 +136,18 @@
     bool mRunning;
     bool mStopped;
 
+    sp<IPowerManager>       mPowerManager;
+    sp<IBinder>             mWakeLockToken;
+    const sp<PMDeathRecipient> mDeathRecipient;
+
     static void *ThreadWrapper(void *me);
     void threadEntry();
 
     sp<Event> removeEventFromQueue_l(event_id id);
 
+    void acquireWakeLock_l();
+    void releaseWakeLock_l();
+
     TimedEventQueue(const TimedEventQueue &);
     TimedEventQueue &operator=(const TimedEventQueue &);
 };