Bug 1621684 - Take an audio-playing wakelock when using WebAudio. r=padenot
authorMike Conley <mconley@mozilla.com>
Thu, 26 Mar 2020 08:02:05 +0000
changeset 520641 ac87de0a73e9f3395e50a8d5d18780178debb1c9
parent 520640 2e1f08362eb0a47c3f6ffc90d73e0edcba91cfa0
child 520642 00bde57608b3936cefbe06a383f3b3f351045dcf
push id37254
push usernerli@mozilla.com
push dateFri, 27 Mar 2020 04:48:07 +0000
treeherdermozilla-central@2d758b42bd73 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1621684
milestone76.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1621684 - Take an audio-playing wakelock when using WebAudio. r=padenot Differential Revision: https://phabricator.services.mozilla.com/D67544
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webaudio/AudioDestinationNode.h
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -5,19 +5,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AudioDestinationNode.h"
 #include "AudioContext.h"
 #include "AlignmentUtils.h"
 #include "AudioContext.h"
 #include "CubebUtils.h"
 #include "mozilla/dom/AudioDestinationNodeBinding.h"
+#include "mozilla/dom/BaseAudioContextBinding.h"
 #include "mozilla/dom/OfflineAudioCompletionEvent.h"
+#include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/BaseAudioContextBinding.h"
+#include "mozilla/dom/WakeLock.h"
 #include "AudioChannelService.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeTrack.h"
 #include "MediaTrackGraph.h"
 #include "nsContentUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsServiceManagerUtils.h"
@@ -339,20 +341,24 @@ AudioDestinationNode::AudioDestinationNo
         aContext->GetMainThread(), "AudioDestinationNode OnRunning",
         [context = RefPtr<AudioContext>(aContext)] {
           context->OnStateChanged(nullptr, AudioContextState::Running);
         },
         [] {
           NS_WARNING(
               "AudioDestinationNode's graph never started processing audio");
         });
+
+    CreateAudioWakeLockIfNeeded();
   }
 }
 
-AudioDestinationNode::~AudioDestinationNode() = default;
+AudioDestinationNode::~AudioDestinationNode() {
+  ReleaseAudioWakeLockIfExists();
+}
 
 size_t AudioDestinationNode::SizeOfExcludingThis(
     MallocSizeOf aMallocSizeOf) const {
   size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
   // Might be useful in the future:
   // - mAudioChannelAgent
   return amount;
 }
@@ -478,21 +484,23 @@ void AudioDestinationNode::Mute() {
 void AudioDestinationNode::Unmute() {
   MOZ_ASSERT(Context() && !Context()->IsOffline());
   SendDoubleParameterToTrack(DestinationNodeEngine::VOLUME, 1.0f);
 }
 
 void AudioDestinationNode::Suspend() {
   DestroyAudioChannelAgent();
   SendInt32ParameterToTrack(DestinationNodeEngine::SUSPENDED, 1);
+  ReleaseAudioWakeLockIfExists();
 }
 
 void AudioDestinationNode::Resume() {
   CreateAudioChannelAgent();
   SendInt32ParameterToTrack(DestinationNodeEngine::SUSPENDED, 0);
+  CreateAudioWakeLockIfNeeded();
 }
 
 void AudioDestinationNode::OfflineShutdown() {
   MOZ_ASSERT(Context() && Context()->IsOffline(),
              "Should only be called on a valid OfflineAudioContext");
 
   if (mTrack) {
     MediaTrackGraph::DestroyNonRealtimeInstance(mTrack->Graph());
@@ -609,16 +617,36 @@ void AudioDestinationNode::StartAudioCap
 }
 
 void AudioDestinationNode::StopAudioCapturingTrack() {
   MOZ_ASSERT(IsCapturingAudio());
   mCaptureTrackPort->Destroy();
   mCaptureTrackPort = nullptr;
 }
 
+void AudioDestinationNode::CreateAudioWakeLockIfNeeded() {
+  if (!mWakeLock) {
+    RefPtr<power::PowerManagerService> pmService =
+        power::PowerManagerService::GetInstance();
+    NS_ENSURE_TRUE_VOID(pmService);
+
+    ErrorResult rv;
+    mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("audio-playing"),
+                                       GetOwner(), rv);
+  }
+}
+
+void AudioDestinationNode::ReleaseAudioWakeLockIfExists() {
+  if (mWakeLock) {
+    IgnoredErrorResult rv;
+    mWakeLock->Unlock(rv);
+    mWakeLock = nullptr;
+  }
+}
+
 nsresult AudioDestinationNode::CreateAudioChannelAgent() {
   if (mIsOffline || mAudioChannelAgent) {
     return NS_OK;
   }
 
   mAudioChannelAgent = new AudioChannelAgent();
   nsresult rv = mAudioChannelAgent->InitWithWeakCallback(GetOwner(), this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/media/webaudio/AudioDestinationNode.h
+++ b/dom/media/webaudio/AudioDestinationNode.h
@@ -11,16 +11,17 @@
 #include "AudioNode.h"
 #include "AudioChannelAgent.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioContext;
+class WakeLock;
 
 class AudioDestinationNode final : public AudioNode,
                                    public nsIAudioChannelAgentCallback,
                                    public MainThreadMediaTrackListener {
  public:
   // This node type knows what MediaTrackGraph to use based on
   // whether it's in offline mode.
   AudioDestinationNode(AudioContext* aContext, bool aIsOffline,
@@ -79,24 +80,27 @@ class AudioDestinationNode final : publi
  private:
   // These function are related to audio capturing. We would start capturing
   // audio if we're starting capturing audio from whole window, and MUST stop
   // capturing explicitly when we don't need to capture audio any more, because
   // we have to release the resource we allocated before.
   bool IsCapturingAudio() const;
   void StartAudioCapturingTrack();
   void StopAudioCapturingTrack();
+  void CreateAudioWakeLockIfNeeded();
+  void ReleaseAudioWakeLockIfExists();
 
   SelfReference<AudioDestinationNode> mOfflineRenderingRef;
   uint32_t mFramesToProduce;
 
   RefPtr<AudioChannelAgent> mAudioChannelAgent;
   RefPtr<MediaInputPort> mCaptureTrackPort;
 
   RefPtr<Promise> mOfflineRenderingPromise;
+  RefPtr<WakeLock> mWakeLock;
 
   bool mIsOffline;
   bool mAudioChannelSuspended;
 
   AudioChannelService::AudibleState mAudible;
 
   // These varaibles are used to know how long AudioContext would become audible
   // since it was created.