summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/TimedEventQueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/TimedEventQueue.cpp')
-rw-r--r--media/libstagefright/TimedEventQueue.cpp82
1 files changed, 79 insertions, 3 deletions
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 7e9c4bf..6a16bb4 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -31,17 +31,26 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
+#include <binder/IServiceManager.h>
+#include <powermanager/PowerManager.h>
+#include <binder/IPCThreadState.h>
+#include <utils/CallStack.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 +85,11 @@ void TimedEventQueue::stop(bool flush) {
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 +131,9 @@ TimedEventQueue::event_id TimedEventQueue::postTimedEvent(
mQueueHeadChangedCondition.signal();
}
+ if (mQueue.empty()) {
+ acquireWakeLock_l();
+ }
mQueue.insert(it, item);
mQueueNotEmptyCondition.signal();
@@ -172,7 +189,9 @@ void TimedEventQueue::cancelEvents(
(*it).event->setEventID(0);
it = mQueue.erase(it);
-
+ if (mQueue.empty()) {
+ releaseWakeLock_l();
+ }
if (stopAfterFirstMatch) {
return;
}
@@ -280,7 +299,9 @@ sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
event->setEventID(0);
mQueue.erase(it);
-
+ if (mQueue.empty()) {
+ releaseWakeLock_l();
+ }
return event;
}
}
@@ -290,5 +311,60 @@ sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
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();
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16("TimedEventQueue"),
+ String16("media"));
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ }
+}
+
+void TimedEventQueue::releaseWakeLock_l()
+{
+ if (mWakeLockToken == 0) {
+ return;
+ }
+ if (mPowerManager != 0) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+ 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