Bug 1373888 - part7 : modify platform wakelocks. draft
authorAlastor Wu <alwu@mozilla.com>
Tue, 29 Aug 2017 15:28:23 +0800
changeset 654756 0cb777f01d296511fad45ee5ba5d8433b405b7da
parent 654755 73ab88c767be6926abd51d39bcfc40e41bf3bd49
child 654757 fed0c1c5b224545a6451689836d23ef2a977add8
push id76666
push useralwu@mozilla.com
push dateTue, 29 Aug 2017 07:28:48 +0000
bugs1373888
milestone57.0a1
Bug 1373888 - part7 : modify platform wakelocks. * OSX Make the lock of the type kIOPMAssertionTypeNoDisplaySleep and kIOPMAssertionTypeNoIdleSleep as a singleton. Won't need to require an extra lock. * Windows Add |mRequireForDisplay| to ensure the "audio-playing" won't overwrite the previous display requirement. * Android Add "audio-playing" and "video-playing", and make sure the audio-lock won't be cancel when receiving "WakeLockDelegate.STATE_LOCKED_BACKGROUND". MozReview-Commit-ID: 97oNX7H2qij
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/WakeLockDelegate.java
widget/cocoa/nsAppShell.mm
widget/windows/nsAppShell.cpp
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -525,23 +525,31 @@ public class GeckoAppShell
                                   // scope, so we need to suppress the linter warning.
         public void setWakeLockState(final String lock, final int state) {
             if (mWakeLocks == null) {
                 mWakeLocks = new SimpleArrayMap<>(WakeLockDelegate.LOCKS_COUNT);
             }
 
             PowerManager.WakeLock wl = mWakeLocks.get(lock);
 
+            // we should still hold the lock for background audio.
+            if (WakeLockDelegate.LOCK_AUDIO_PLAYING.equals(lock) &&
+                state == WakeLockDelegate.STATE_LOCKED_BACKGROUND) {
+                return;
+            }
+
             if (state == WakeLockDelegate.STATE_LOCKED_FOREGROUND && wl == null) {
                 final PowerManager pm = (PowerManager)
                         getApplicationContext().getSystemService(Context.POWER_SERVICE);
 
-                if (WakeLockDelegate.LOCK_CPU.equals(lock)) {
+                if (WakeLockDelegate.LOCK_CPU.equals(lock) ||
+                    WakeLockDelegate.LOCK_AUDIO_PLAYING.equals(lock)) {
                   wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lock);
-                } else if (WakeLockDelegate.LOCK_SCREEN.equals(lock)) {
+                } else if (WakeLockDelegate.LOCK_SCREEN.equals(lock) ||
+                           WakeLockDelegate.LOCK_VIDEO_PLAYING.equals(lock)) {
                   // ON_AFTER_RELEASE is set, the user activity timer will be reset when the
                   // WakeLock is released, causing the illumination to remain on a bit longer.
                   wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
                                       PowerManager.ON_AFTER_RELEASE, lock);
                 } else {
                     Log.w(LOGTAG, "Unsupported wake-lock: " + lock);
                     return;
                 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/WakeLockDelegate.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/WakeLockDelegate.java
@@ -12,16 +12,24 @@ public interface WakeLockDelegate {
     /**
      * Wake-lock for the CPU.
      */
     final String LOCK_CPU = "cpu";
     /**
      * Wake-lock for the screen.
      */
     final String LOCK_SCREEN = "screen";
+    /**
+     * Wake-lock for the audio-playing, eqaul to LOCK_CPU.
+     */
+    final String LOCK_AUDIO_PLAYING = "audio-playing";
+    /**
+     * Wake-lock for the video-playing, eqaul to LOCK_SCREEN..
+     */
+    final String LOCK_VIDEO_PLAYING = "video-playing";
 
     final int LOCKS_COUNT = 2;
 
     /**
      * No one holds the wake-lock.
      */
     final int STATE_UNLOCKED = 0;
     /**
--- a/widget/cocoa/nsAppShell.mm
+++ b/widget/cocoa/nsAppShell.mm
@@ -62,26 +62,35 @@ private:
 
   NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) override {
     if (!aTopic.EqualsASCII("screen") &&
         !aTopic.EqualsASCII("audio-playing") &&
         !aTopic.EqualsASCII("video-playing")) {
       return NS_OK;
     }
 
+    // we should still hold the lock for background audio.
+    if (aTopic.EqualsASCII("audio-playing") &&
+        aState.EqualsASCII("locked-background")) {
+      return NS_OK;
+    }
+
     bool shouldKeepDisplayOn = aTopic.EqualsASCII("screen") ||
                                aTopic.EqualsASCII("video-playing");
     CFStringRef assertionType = shouldKeepDisplayOn ?
       kIOPMAssertionTypeNoDisplaySleep : kIOPMAssertionTypeNoIdleSleep;
     IOPMAssertionID& assertionId = shouldKeepDisplayOn ?
       mAssertionNoDisplaySleepID : mAssertionNoIdleSleepID;
 
     // Note the wake lock code ensures that we're not sent duplicate
     // "locked-foreground" notifications when multiple wake locks are held.
     if (aState.EqualsASCII("locked-foreground")) {
+      if (assertionId != kIOPMNullAssertionID) {
+        return NS_OK;
+      }
       // Prevent screen saver.
       CFStringRef cf_topic =
         ::CFStringCreateWithCharacters(kCFAllocatorDefault,
                                        reinterpret_cast<const UniChar*>
                                          (aTopic.Data()),
                                        aTopic.Length());
       IOReturn success =
         ::IOPMAssertionCreateWithName(assertionType,
@@ -95,16 +104,17 @@ private:
     } else {
       // Re-enable screen saver.
       NS_WARNING("Releasing screensaver");
       if (assertionId != kIOPMNullAssertionID) {
         IOReturn result = ::IOPMAssertionRelease(assertionId);
         if (result != kIOReturnSuccess) {
           NS_WARNING("failed to release screensaver");
         }
+        assertionId = kIOPMNullAssertionID;
       }
     }
     return NS_OK;
   }
 }; // MacWakeLockListener
 
 // defined in nsCocoaWindow.mm
 extern int32_t             gXULModalLevel;
--- a/widget/windows/nsAppShell.cpp
+++ b/widget/windows/nsAppShell.cpp
@@ -40,46 +40,58 @@ using namespace mozilla::widget;
 static mozilla::LazyLogModule gWinWakeLockLog("WinWakeLock");
 
 // A wake lock listener that disables screen saver when requested by
 // Gecko. For example when we're playing video in a foreground tab we
 // don't want the screen saver to turn on.
 class WinWakeLockListener final : public nsIDOMMozWakeLockListener
 {
 public:
-  NS_DECL_ISUPPORTS;
+  NS_DECL_ISUPPORTS
 
 private:
   ~WinWakeLockListener() {}
 
   NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) {
     if (!aTopic.EqualsASCII("screen") &&
         !aTopic.EqualsASCII("audio-playing") &&
         !aTopic.EqualsASCII("video-playing")) {
       return NS_OK;
     }
-    bool shouldKeepDisplayOn = aTopic.EqualsASCII("screen") ||
-                               aTopic.EqualsASCII("video-playing");
+
+    // we should still hold the lock for background audio.
+    if (aTopic.EqualsASCII("audio-playing") &&
+        aState.EqualsASCII("locked-background")) {
+      return NS_OK;
+    }
+
+    if (aTopic.EqualsASCII("screen") ||
+        aTopic.EqualsASCII("video-playing")) {
+      mRequireForDisplay = aState.EqualsASCII("locked-foreground");
+    }
+
     // Note the wake lock code ensures that we're not sent duplicate
     // "locked-foreground" notifications when multiple wake locks are held.
     if (aState.EqualsASCII("locked-foreground")) {
       WAKE_LOCK_LOG("WinWakeLock: Blocking screen saver");
-      if (shouldKeepDisplayOn) {
+      if (mRequireForDisplay) {
         // Prevent the display turning off and block the screen saver.
         SetThreadExecutionState(ES_DISPLAY_REQUIRED|ES_CONTINUOUS);
       } else {
         SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_CONTINUOUS);
       }
     } else {
       WAKE_LOCK_LOG("WinWakeLock: Unblocking screen saver");
       // Unblock display/screen saver turning off.
       SetThreadExecutionState(ES_CONTINUOUS);
     }
     return NS_OK;
   }
+
+  bool mRequireForDisplay = false;
 };
 
 NS_IMPL_ISUPPORTS(WinWakeLockListener, nsIDOMMozWakeLockListener)
 StaticRefPtr<WinWakeLockListener> sWakeLockListener;
 
 static void
 AddScreenWakeLockListener()
 {