Bug 1593131 - part2 : dynamically create or destroy media keys event source according to the amount of media controller r=chunmin
authoralwu <alwu@mozilla.com>
Tue, 12 Nov 2019 17:44:32 +0000
changeset 502051 222533f6446ed6f8f544c6e25e10cf344557f62c
parent 502050 d168bfd2524c7c7c5110b7dcbca2f3671779c9ea
child 502052 9d1e133ed17c9525faafff30e632a136a536d807
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschunmin
bugs1593131
milestone72.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 1593131 - part2 : dynamically create or destroy media keys event source according to the amount of media controller r=chunmin In this patch, we dynamically create or destroy media keys event source according to the amount of media controller . We would create the event source when we have a controller which needs to be controlled, and destory the event source when there is no controllers existing. In addition, create a `Init()` function for media service for calling any other owned module's initialization, which is used to ensure that we finish setting the `gMediaControlService` before any other classes call `MediaControlService::GetService()`. Differential Revision: https://phabricator.services.mozilla.com/D51765
dom/media/mediacontrol/MediaControlKeysManager.cpp
dom/media/mediacontrol/MediaControlKeysManager.h
dom/media/mediacontrol/MediaControlService.cpp
dom/media/mediacontrol/MediaControlService.h
--- a/dom/media/mediacontrol/MediaControlKeysManager.cpp
+++ b/dom/media/mediacontrol/MediaControlKeysManager.cpp
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaControlKeysManager.h"
 
 #include "MediaControlUtils.h"
+#include "mozilla/AbstractThread.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Logging.h"
 
 #ifdef MOZ_APPLEMEDIA
 #  include "MediaHardwareKeysEventSourceMac.h"
 #endif
 
 extern mozilla::LazyLogModule gMediaControlLog;
@@ -17,22 +18,27 @@ extern mozilla::LazyLogModule gMediaCont
 #undef LOG
 #define LOG(msg, ...)                        \
   MOZ_LOG(gMediaControlLog, LogLevel::Debug, \
           ("MediaControlKeysManager=%p, " msg, this, ##__VA_ARGS__))
 
 namespace mozilla {
 namespace dom {
 
-MediaControlKeysManager::MediaControlKeysManager() {
-  StartMonitoringControlKeys();
+void MediaControlKeysManager::Init() {
+  mControllerAmountChangedListener =
+      MediaControlService::GetService()
+          ->MediaControllerAmountChangedEvent()
+          .Connect(AbstractThread::MainThread(), this,
+                   &MediaControlKeysManager::ControllerAmountChanged);
 }
 
 MediaControlKeysManager::~MediaControlKeysManager() {
   StopMonitoringControlKeys();
+  mControllerAmountChangedListener.DisconnectIfExists();
 }
 
 void MediaControlKeysManager::StartMonitoringControlKeys() {
   LOG("StartMonitoringControlKeys");
   if (!StaticPrefs::media_hardwaremediakeys_enabled()) {
     return;
   }
   CreateEventSource();
@@ -47,16 +53,26 @@ void MediaControlKeysManager::CreateEven
 void MediaControlKeysManager::StopMonitoringControlKeys() {
   LOG("StopMonitoringControlKeys");
   if (mEventSource) {
     mEventSource->Close();
     mEventSource = nullptr;
   }
 }
 
+void MediaControlKeysManager::ControllerAmountChanged(
+    uint64_t aControllerAmount) {
+  LOG("Controller amount changed=%" PRId64, aControllerAmount);
+  if (aControllerAmount > 0 && !mEventSource) {
+    StartMonitoringControlKeys();
+  } else if (aControllerAmount == 0 && mEventSource) {
+    StopMonitoringControlKeys();
+  }
+}
+
 bool MediaControlKeysManager::AddListener(
     MediaControlKeysEventListener* aListener) {
   if (!mEventSource) {
     LOG("No event source for adding a listener");
     return false;
   }
   mEventSource->AddListener(aListener);
   return true;
--- a/dom/media/mediacontrol/MediaControlKeysManager.h
+++ b/dom/media/mediacontrol/MediaControlKeysManager.h
@@ -1,40 +1,49 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DOM_MEDIA_MEDIACONTROL_MEDIACONTROLKEYSMANAGER_H_
 #define DOM_MEDIA_MEDIACONTROL_MEDIACONTROLKEYSMANAGER_H_
 
 #include "MediaControlKeysEvent.h"
+#include "MediaEventSource.h"
 
 namespace mozilla {
 namespace dom {
 
 /**
- * MediaControlKeysManager is used to manage a source, which can globally
- * receive media control keys event, such as play, pause. It provides methods
- * to add or remove a listener to the source in order to listen media control
- * keys event.
+ * MediaControlKeysManager is a wrapper of MediaControlKeysEventSource, which
+ * is used to manage creating and destroying a real media keys event source.
+ *
+ * It monitors the amount of the media controller in MediaService, and would
+ * create the event source when there is any existing controller and destroy it
+ * when there is no controller.
  */
 class MediaControlKeysManager final {
  public:
-  MediaControlKeysManager();
+  MediaControlKeysManager() = default;
   ~MediaControlKeysManager();
 
   // Return false when there is no event source created, so that we are not able
   // to add or remove listener, otherwise, calling these methods should always
   // succeed.
   bool AddListener(MediaControlKeysEventListener* aListener);
   bool RemoveListener(MediaControlKeysEventListener* aListener);
+  void Init();
+
+  // The callback function for monitoring the media controller amount changed
+  // event.
+  void ControllerAmountChanged(uint64_t aControllerAmount);
 
  private:
   void StartMonitoringControlKeys();
   void StopMonitoringControlKeys();
   void CreateEventSource();
   RefPtr<MediaControlKeysEventSource> mEventSource;
+  MediaEventListener mControllerAmountChangedListener;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif
--- a/dom/media/mediacontrol/MediaControlService.cpp
+++ b/dom/media/mediacontrol/MediaControlService.cpp
@@ -30,16 +30,17 @@ static bool sIsXPCOMShutdown = false;
 RefPtr<MediaControlService> MediaControlService::GetService() {
   MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(),
                         "MediaControlService only runs on Chrome process!");
   if (sIsXPCOMShutdown) {
     return nullptr;
   }
   if (!gMediaControlService) {
     gMediaControlService = new MediaControlService();
+    gMediaControlService->Init();
   }
   RefPtr<MediaControlService> service = gMediaControlService.get();
   return service;
 }
 
 NS_INTERFACE_MAP_BEGIN(MediaControlService)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
@@ -49,17 +50,21 @@ NS_IMPL_ADDREF(MediaControlService)
 NS_IMPL_RELEASE(MediaControlService)
 
 MediaControlService::MediaControlService() : mAudioFocusManager(this) {
   LOG("create media control service");
   RefPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->AddObserver(this, "xpcom-shutdown", false);
   }
+}
+
+void MediaControlService::Init() {
   mMediaKeysHandlder = new MediaControlKeysHandler();
+  GetMediaControlKeysManager().Init();
   GetMediaControlKeysManager().AddListener(mMediaKeysHandlder.get());
 }
 
 MediaControlService::~MediaControlService() {
   LOG("destroy media control service");
   Shutdown();
 }
 
--- a/dom/media/mediacontrol/MediaControlService.h
+++ b/dom/media/mediacontrol/MediaControlService.h
@@ -54,16 +54,17 @@ class MediaControlService final : public
   MediaEventSource<uint64_t>& MediaControllerAmountChangedEvent() {
     return mMediaControllerAmountChangedEvent;
   }
 
  private:
   MediaControlService();
   ~MediaControlService();
 
+  void Init();
   void Shutdown();
 
   void PlayAllControllers() const;
   void PauseAllControllers() const;
   void StopAllControllers() const;
   void ShutdownAllControllers() const;
 
   nsDataHashtable<nsUint64HashKey, RefPtr<MediaController>> mControllers;