Bug 1501869 - Part 2: Stop calling VR tasks when they are at background. r=kip
☠☠ backed out by 279ffbe01845 ☠ ☠
authorDaosheng Mu <daoshengmu@gmail.com>
Fri, 26 Oct 2018 17:26:32 +0000
changeset 443200 56896b0e10d3a554e329de778247ff60265c96e3
parent 443199 cdb87cbfe882997bdcbd39d5380738a42aa07a27
child 443201 bb39d23d1da6547ad386ad94bae1a76938862f02
push id34944
push userncsoregi@mozilla.com
push dateSat, 27 Oct 2018 09:49:55 +0000
treeherdermozilla-central@49d47a692ca4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1501869
milestone65.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 1501869 - Part 2: Stop calling VR tasks when they are at background. r=kip Differential Revision: https://phabricator.services.mozilla.com/D9880
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsGlobalWindowOuter.cpp
dom/vr/VREventObserver.cpp
dom/vr/VREventObserver.h
gfx/vr/VRManager.h
gfx/vr/ipc/PVRManager.ipdl
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerChild.h
gfx/vr/ipc/VRManagerParent.cpp
gfx/vr/ipc/VRManagerParent.h
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -4441,16 +4441,32 @@ nsGlobalWindowInner::DisableVRUpdates()
 void
 nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate)
 {
   if (mVREventObserver) {
     mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
   }
 }
 
+void
+nsGlobalWindowInner::StartVRActivity()
+{
+  if (mVREventObserver) {
+    mVREventObserver->StartActivity();
+  }
+}
+
+void
+nsGlobalWindowInner::StopVRActivity()
+{
+  if (mVREventObserver) {
+    mVREventObserver->StopActivity();
+  }
+}
+
 #ifndef XP_WIN // This guard should match the guard at the callsite.
 static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
 {
   if (!aNode) {
     return true;
   }
   return !nsContentUtils::ContentIsLink(aNode) &&
     !aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -554,16 +554,19 @@ public:
   // Enable/disable updates for VR
   void EnableVRUpdates();
   void DisableVRUpdates();
   // Reset telemetry data when switching windows.
   // aUpdate, true for accumulating the result to the histogram.
   // false for only resetting the timestamp.
   void ResetVRTelemetry(bool aUpdate);
 
+  void StartVRActivity();
+  void StopVRActivity();
+
   // Update the VR displays for this window
   bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
 
   // Inner windows only.
   // Called to inform that the set of active VR displays has changed.
   void NotifyActiveVRDisplaysChanged();
   void NotifyPresentationGenerationChanged(uint32_t aDisplayID);
 
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -6630,28 +6630,30 @@ nsGlobalWindowOuter::SetIsBackground(boo
 
   if (aIsBackground) {
     // Notify gamepadManager we are at the background window,
     // we need to stop vibrate.
     // Stop the vr telemery time spent when it switches to
     // the background window.
     if (inner && changed) {
       inner->StopGamepadHaptics();
+      inner->StopVRActivity();
       // true is for asking to set the delta time to
       // the telemetry.
       inner->ResetVRTelemetry(true);
     }
     return;
   }
 
   if (inner) {
     // When switching to be as a top tab, restart the telemetry.
     // false is for only resetting the timestamp.
     inner->ResetVRTelemetry(false);
     inner->SyncGamepadState();
+    inner->StartVRActivity();
   }
 }
 
 void
 nsGlobalWindowOuter::SetIsBackgroundInternal(bool aIsBackground)
 {
   if (mIsBackground != aIsBackground) {
     TabGroup()->WindowChangedBackgroundStatus(aIsBackground);
--- a/dom/vr/VREventObserver.cpp
+++ b/dom/vr/VREventObserver.cpp
@@ -21,16 +21,17 @@ using namespace gfx;
  * This class is used by nsGlobalWindow to implement window.onvrdisplayactivate,
  * window.onvrdisplaydeactivate, window.onvrdisplayconnected,
  * window.onvrdisplaydisconnected, and window.onvrdisplaypresentchange.
  */
 VREventObserver::VREventObserver(nsGlobalWindowInner* aGlobalWindow)
   : mWindow(aGlobalWindow)
   , mIs2DView(true)
   , mHasReset(false)
+  , mStopActivity(false)
 {
   MOZ_ASSERT(aGlobalWindow);
 
   UpdateSpentTimeIn2DTelemetry(false);
   VRManagerChild* vmc = VRManagerChild::Get();
   if (vmc) {
     vmc->AddListener(this);
   }
@@ -50,16 +51,17 @@ VREventObserver::DisconnectFromOwner()
   UpdateSpentTimeIn2DTelemetry(true);
   mWindow = nullptr;
 
   // Unregister from VRManagerChild
   if (VRManagerChild::IsCreated()) {
     VRManagerChild* vmc = VRManagerChild::Get();
     vmc->RemoveListener(this);
   }
+  mStopActivity = true;
 }
 
 void
 VREventObserver::UpdateSpentTimeIn2DTelemetry(bool aUpdate)
 {
   // mHasReset for avoiding setting the telemetry continuously
   // for the telemetry is already been set when it is at the background.
   // then, it would be set again when the process is exit and calling
@@ -73,16 +75,38 @@ VREventObserver::UpdateSpentTimeIn2DTele
     mHasReset = false;
   } else if (!aUpdate) {
     mSpendTimeIn2DView = TimeStamp::Now();
     mHasReset = true;
   }
 }
 
 void
+VREventObserver::StartActivity()
+{
+  mStopActivity = false;
+  VRManagerChild* vmc = VRManagerChild::Get();
+  vmc->StartActivity();
+}
+
+void
+VREventObserver::StopActivity()
+{
+  mStopActivity = true;
+  VRManagerChild* vmc = VRManagerChild::Get();
+  vmc->StopActivity();
+}
+
+bool
+VREventObserver::GetStopActivityStatus()
+{
+  return mStopActivity;
+}
+
+void
 VREventObserver::NotifyAfterLoad()
 {
   if (VRManagerChild::IsCreated()) {
     VRManagerChild* vmc = VRManagerChild::Get();
     vmc->FireDOMVRDisplayConnectEventsForLoad(this);
   }
 }
 
--- a/dom/vr/VREventObserver.h
+++ b/dom/vr/VREventObserver.h
@@ -28,24 +28,28 @@ public:
   void NotifyVRDisplayRequested(uint32_t aDisplayID);
   void NotifyVRDisplayConnect(uint32_t aDisplayID);
   void NotifyVRDisplayDisconnect(uint32_t aDisplayID);
   void NotifyVRDisplayPresentChange(uint32_t aDisplayID);
   void NotifyPresentationGenerationChanged(uint32_t aDisplayID);
 
   void DisconnectFromOwner();
   void UpdateSpentTimeIn2DTelemetry(bool aUpdate);
+  void StartActivity();
+  void StopActivity();
+  bool GetStopActivityStatus();
 
 private:
   ~VREventObserver();
 
   RefPtr<nsGlobalWindowInner> mWindow;
   // For WebVR telemetry for tracking users who view content
   // in the 2D view.
   TimeStamp mSpendTimeIn2DView;
   bool mIs2DView;
   bool mHasReset;
+  bool mStopActivity;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_VREventObserver_h
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -28,17 +28,16 @@ class VRDisplayHost;
 class VRService;
 #endif
 class VRSystemManagerPuppet;
 class VRSystemManagerExternal;
 
 class VRManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::gfx::VRManager)
-  friend class VRManagerParent;
 
 public:
   static void ManagerInit();
   static VRManager* Get();
 
   void AddVRManagerParent(VRManagerParent* aVRManagerParent);
   void RemoveVRManagerParent(VRManagerParent* aVRManagerParent);
 
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -62,16 +62,18 @@ parent:
 
   async NewButtonEventToMockController(uint32_t aDeviceID, long aButton,
                                        bool aPressed);
   async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
                                          double aValue);
   async NewPoseMoveToMockController(uint32_t aDeviceID, GamepadPoseState aPose);
   async StartVRNavigation(uint32_t aDeviceID);
   async StopVRNavigation(uint32_t aDeviceID, TimeDuration aDuration);
+  async StartActivity();
+  async StopActivity();
 
 child:
   // Notify children of updated VR display enumeration and details.  This will
   // be sent to all children when the parent receives RefreshDisplays, even
   // if no changes have been detected.  This ensures that Promises exposed
   // through DOM calls are always resolved.
   async UpdateDisplayInfo(VRDisplayInfo[] aDisplayUpdates);
 
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -614,16 +614,35 @@ VRManagerChild::RemoveListener(dom::VREv
 
   mListeners.RemoveElement(aObserver);
   if (mListeners.IsEmpty()) {
     Unused << SendSetHaveEventListener(false);
   }
 }
 
 void
+VRManagerChild::StartActivity()
+{
+  Unused << SendStartActivity();
+}
+
+void
+VRManagerChild::StopActivity()
+{
+  for (auto& listener : mListeners) {
+    if (!listener->GetStopActivityStatus()) {
+      // We are still showing VR in the active window.
+      return;
+    }
+  }
+
+  Unused << SendStopActivity();
+}
+
+void
 VRManagerChild::HandleFatalError(const char* aMsg) const
 {
   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
 }
 
 void
 VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
 {
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -37,16 +37,18 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRManagerChild);
 
   static VRManagerChild* Get();
 
   // Indicate that an observer wants to receive VR events.
   void AddListener(dom::VREventObserver* aObserver);
   // Indicate that an observer should no longer receive VR events.
   void RemoveListener(dom::VREventObserver* aObserver);
+  void StartActivity();
+  void StopActivity();
 
   bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
   bool RefreshVRDisplaysWithCallback(uint64_t aWindowId);
   void AddPromise(const uint32_t& aID, dom::Promise* aPromise);
 
   void CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise);
   void CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise);
 
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -19,16 +19,17 @@ namespace mozilla {
 using namespace layers;
 namespace gfx {
 
 VRManagerParent::VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild)
   : mControllerTestID(1)
   , mHaveEventListener(false)
   , mHaveControllerListener(false)
   , mIsContentChild(aIsContentChild)
+  , mVRActiveStatus(true)
 {
   MOZ_COUNT_CTOR(VRManagerParent);
   MOZ_ASSERT(NS_IsMainThread());
 
   SetOtherProcessId(aChildProcessId);
 }
 
 VRManagerParent::~VRManagerParent()
@@ -199,25 +200,35 @@ VRManagerParent::RecvSetGroupMask(const 
     display->SetGroupMask(aGroupMask);
   }
   return IPC_OK();
 }
 
 bool
 VRManagerParent::HaveEventListener()
 {
+  if (!mVRActiveStatus) {
+    return false;
+  }
+
   return mHaveEventListener;
 }
 
 bool
 VRManagerParent::HaveControllerListener()
 {
   return mHaveControllerListener;
 }
 
+bool
+VRManagerParent::GetVRActiveStatus()
+{
+  return mVRActiveStatus;
+}
+
 mozilla::ipc::IPCResult
 VRManagerParent::RecvSetHaveEventListener(const bool& aHaveEventListener)
 {
   mHaveEventListener = aHaveEventListener;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -464,10 +475,24 @@ VRManagerParent::RecvStartVRNavigation(c
 mozilla::ipc::IPCResult
 VRManagerParent::RecvStopVRNavigation(const uint32_t& aDeviceID, const TimeDuration& aTimeout)
 {
   VRManager* vm = VRManager::Get();
   vm->StopVRNavigation(aDeviceID, aTimeout);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+VRManagerParent::RecvStartActivity()
+{
+  mVRActiveStatus = true;
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRManagerParent::RecvStopActivity()
+{
+  mVRActiveStatus = false;
+  return IPC_OK();
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -34,16 +34,17 @@ public:
 
   static VRManagerParent* CreateSameProcess();
   static bool CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint);
   static bool CreateForContent(Endpoint<PVRManagerParent>&& aEndpoint);
 
   bool IsSameProcess() const;
   bool HaveEventListener();
   bool HaveControllerListener();
+  bool GetVRActiveStatus();
   bool SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent);
   bool SendReplyGamepadVibrateHaptic(const uint32_t& aPromiseID);
 
 protected:
   ~VRManagerParent();
 
   virtual PVRLayerParent* AllocPVRLayerParent(const uint32_t& aDisplayID,
                                               const uint32_t& aGroup) override;
@@ -70,16 +71,19 @@ protected:
                                                                   const VRHMDSensorState& aSensorState) override;
   virtual mozilla::ipc::IPCResult RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
                                                                      const bool& aPressed) override;
   virtual mozilla::ipc::IPCResult RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
                                                                        const double& aValue) override;
   virtual mozilla::ipc::IPCResult RecvNewPoseMoveToMockController(const uint32_t& aDeviceID, const GamepadPoseState& pose) override;
   virtual mozilla::ipc::IPCResult RecvStartVRNavigation(const uint32_t& aDeviceID) override;
   virtual mozilla::ipc::IPCResult RecvStopVRNavigation(const uint32_t& aDeviceID, const TimeDuration& aTimeout) override;
+  virtual mozilla::ipc::IPCResult RecvStartActivity() override;
+  virtual mozilla::ipc::IPCResult RecvStopActivity() override;
+
 private:
   void RegisterWithManager();
   void UnregisterFromManager();
 
   void Bind(Endpoint<PVRManagerParent>&& aEndpoint);
 
   static void RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager);
 
@@ -94,16 +98,20 @@ private:
 
   // Keep the VRManager alive, until we have destroyed ourselves.
   RefPtr<VRManager> mVRManagerHolder;
   nsRefPtrHashtable<nsUint32HashKey, impl::VRControllerPuppet> mVRControllerTests;
   uint32_t mControllerTestID;
   bool mHaveEventListener;
   bool mHaveControllerListener;
   bool mIsContentChild;
+
+  // When VR tabs are switched the background, we won't need to
+  // initialize its session in VRService thread.
+  bool mVRActiveStatus;
 };
 
 class VRManagerPromise final
 {
   friend class VRManager;
 
 public:
   explicit VRManagerPromise(RefPtr<VRManagerParent> aParent, uint32_t aPromiseID)