Bug 1059700 - AudioOffloadPlayer: Use wakelock to avoid suspend between pause and reset. r=roc, a=bajaj
authorVasanthakumar Pandurangan <vasanth@codeaurora.org>
Wed, 24 Sep 2014 01:22:57 -0700
changeset 225196 76584e88ee70baa78269a7ce6b0baa151fadc5a4
parent 225195 294e6eb3cd56cf2f867edb5188eb4435de5338c2
child 225197 38ad67d1f18585c222056fcec621d1f41a54807a
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, bajaj
bugs1059700
milestone34.0a2
Bug 1059700 - AudioOffloadPlayer: Use wakelock to avoid suspend between pause and reset. r=roc, a=bajaj
content/media/omx/AudioOffloadPlayer.cpp
content/media/omx/AudioOffloadPlayer.h
--- a/content/media/omx/AudioOffloadPlayer.cpp
+++ b/content/media/omx/AudioOffloadPlayer.cpp
@@ -17,16 +17,18 @@
  * limitations under the License.
  */
 
 #include "AudioOffloadPlayer.h"
 #include "nsComponentManagerUtils.h"
 #include "nsITimer.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "VideoUtils.h"
+#include "mozilla/dom/power/PowerManagerService.h"
+#include "mozilla/dom/WakeLock.h"
 
 #include <binder/IPCThreadState.h>
 #include <stagefright/foundation/ADebug.h>
 #include <stagefright/foundation/ALooper.h>
 #include <stagefright/MediaDefs.h>
 #include <stagefright/MediaErrors.h>
 #include <stagefright/MediaSource.h>
 #include <stagefright/MetaData.h>
@@ -210,28 +212,31 @@ status_t AudioOffloadPlayer::ChangeState
     default:
       break;
   }
   return OK;
 }
 
 static void ResetCallback(nsITimer* aTimer, void* aClosure)
 {
+  AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __FUNCTION__));
   AudioOffloadPlayer* player = static_cast<AudioOffloadPlayer*>(aClosure);
   if (player) {
     player->Reset();
   }
 }
 
 void AudioOffloadPlayer::Pause(bool aPlayPendingSamples)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mStarted) {
     CHECK(mAudioSink.get());
+    WakeLockCreate();
+
     if (aPlayPendingSamples) {
       mAudioSink->Stop();
     } else {
       mAudioSink->Pause();
     }
     mPlaying = false;
   }
 
@@ -247,16 +252,17 @@ void AudioOffloadPlayer::Pause(bool aPla
 
 status_t AudioOffloadPlayer::Play()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mResetTimer) {
     mResetTimer->Cancel();
     mResetTimer = nullptr;
+    WakeLockRelease();
   }
 
   status_t err = OK;
 
   if (!mStarted) {
     // Last pause timed out and offloaded audio sink was reset. Start it again
     err = Start(false);
     if (err != OK) {
@@ -276,16 +282,17 @@ status_t AudioOffloadPlayer::Play()
     }
   }
 
   return err;
 }
 
 void AudioOffloadPlayer::Reset()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   if (!mStarted) {
     return;
   }
 
   CHECK(mAudioSink.get());
 
   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("reset: mPlaying=%d mReachedEOS=%d",
       mPlaying, mReachedEOS));
@@ -318,16 +325,18 @@ void AudioOffloadPlayer::Reset()
 
   IPCThreadState::self()->flushCommands();
   StopTimeUpdate();
 
   mReachedEOS = false;
   mStarted = false;
   mPlaying = false;
   mStartPosUs = 0;
+
+  WakeLockRelease();
 }
 
 status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents)
 {
   MOZ_ASSERT(NS_IsMainThread());
   CHECK(mAudioSink.get());
 
   android::Mutex::Autolock autoLock(mLock);
@@ -706,9 +715,35 @@ void AudioOffloadPlayer::SendMetaDataToH
 
 void AudioOffloadPlayer::SetVolume(double aVolume)
 {
   MOZ_ASSERT(NS_IsMainThread());
   CHECK(mAudioSink.get());
   mAudioSink->SetVolume((float) aVolume);
 }
 
+void AudioOffloadPlayer::WakeLockCreate()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __FUNCTION__));
+  if (!mWakeLock) {
+    nsRefPtr<dom::power::PowerManagerService> pmService =
+      dom::power::PowerManagerService::GetInstance();
+    NS_ENSURE_TRUE_VOID(pmService);
+
+    ErrorResult rv;
+    mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("cpu"), nullptr, rv);
+  }
+}
+
+void AudioOffloadPlayer::WakeLockRelease()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __FUNCTION__));
+  if (mWakeLock) {
+    ErrorResult rv;
+    mWakeLock->Unlock(rv);
+    NS_WARN_IF_FALSE(!rv.Failed(), "Failed to unlock the wakelock.");
+    mWakeLock = nullptr;
+  }
+}
+
 } // namespace mozilla
--- a/content/media/omx/AudioOffloadPlayer.h
+++ b/content/media/omx/AudioOffloadPlayer.h
@@ -28,16 +28,20 @@
 
 #include "AudioOutput.h"
 #include "AudioOffloadPlayerBase.h"
 #include "MediaDecoderOwner.h"
 #include "MediaOmxCommonDecoder.h"
 
 namespace mozilla {
 
+namespace dom {
+class WakeLock;
+}
+
 /**
  * AudioOffloadPlayer adds support for audio tunneling to a digital signal
  * processor (DSP) in the device chipset. With tunneling, audio decoding is
  * off-loaded to the DSP, waking the application processor less often and using
  * less battery
  *
  * This depends on offloading capability provided by Android KK AudioTrack class
  *
@@ -188,16 +192,20 @@ private:
   // Timer to trigger position changed events
   nsCOMPtr<nsITimer> mTimeUpdateTimer;
 
   // Timer to reset AudioSink when audio is paused for OFFLOAD_PAUSE_MAX_USECS.
   // It is triggered in Pause() and canceled when there is a Play() within
   // OFFLOAD_PAUSE_MAX_USECS. Used only from main thread so no lock is needed.
   nsCOMPtr<nsITimer> mResetTimer;
 
+  // To avoid device suspend when mResetTimer is going to be triggered.
+  // Used only from main thread so no lock is needed.
+  nsRefPtr<mozilla::dom::WakeLock> mWakeLock;
+
   int64_t GetMediaTimeUs();
 
   // Provide the playback position in microseconds from total number of
   // frames played by audio track
   int64_t GetOutputPlayPositionUs_l() const;
 
   // Fill the buffer given by audio sink with data from compressed audio
   // source. Also handles the seek by seeking audio source and stop the sink in
@@ -235,16 +243,19 @@ private:
   // (>1sec) But when Player UI is visible we need to update progress bar
   // atleast once in 250ms. Start a timer when player UI becomes visible or
   // audio starts playing to send PlaybackPositionChanged events once in 250ms.
   // Stop the timer when UI goes invisible or play state is not playing.
   // Also make sure timer functions are always called from main thread
   nsresult StartTimeUpdate();
   nsresult StopTimeUpdate();
 
+  void WakeLockCreate();
+  void WakeLockRelease();
+
   // Notify end of stream by sending PlaybackEnded event to observer
   // (i.e.MediaDecoder)
   void NotifyAudioEOS();
 
   // Notify position changed event by sending PlaybackPositionChanged event to
   // observer
   void NotifyPositionChanged();