Bug 739913 - Add cpuSleepAllowed attribute to mozPower. r=cjones
authorKan-Ru Chen <kanru@kanru.info>
Mon, 16 Apr 2012 18:35:33 -0400
changeset 95108 ad0867e065d81f52e99fe49eaddf85395bf9bced
parent 95107 e44a95efa5f098cfd5f41d68371a407427f7c7ef
child 95109 7a89be8dbecc75b35093cb58dae0e4f1ec5b3893
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs739913
milestone14.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 739913 - Add cpuSleepAllowed attribute to mozPower. r=cjones
b2g/chrome/content/shell.js
dom/power/PowerManager.cpp
dom/power/nsIDOMPowerManager.idl
hal/Hal.cpp
hal/Hal.h
hal/Makefile.in
hal/fallback/FallbackWakeLocks.cpp
hal/gonk/GonkHal.cpp
hal/sandbox/PHal.ipdl
hal/sandbox/SandboxHal.cpp
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -318,16 +318,20 @@ var shell = {
       if (state != "locked-foreground") {
         if (Services.idle.idleTime > idleTimeout*1000) {
           navigator.mozPower.screenEnabled = false;
         }
       } else {
         navigator.mozPower.screenEnabled = true;
       }
     }
+    if (topic == "cpu") {
+      navigator.mozPower.cpuSleepAllowed = (state != "locked-foreground" &&
+                                            state != "locked-background");
+    }
   }
 
   let idleTimeout = Services.prefs.getIntPref("power.screen.timeout");
   if (!('mozSettings' in navigator))
     return;
 
   let request = navigator.mozSettings.getLock().get("power.screen.timeout");
   request.onsuccess = function onSuccess() {
--- a/dom/power/PowerManager.cpp
+++ b/dom/power/PowerManager.cpp
@@ -231,11 +231,32 @@ PowerManager::SetScreenBrightness(double
 {
   NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG);
   hal::SetScreenBrightness(aBrightness);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+PowerManager::GetCpuSleepAllowed(bool *aAllowed)
+{
+  if (!CheckPermission()) {
+    *aAllowed = true;
+    return NS_OK;
+  }
+
+  *aAllowed = hal::GetCpuSleepAllowed();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManager::SetCpuSleepAllowed(bool aAllowed)
+{
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
+
+  hal::SetCpuSleepAllowed(aAllowed);
+  return NS_OK;
+}
+
 } // power
 } // dom
 } // mozilla
--- a/dom/power/nsIDOMPowerManager.idl
+++ b/dom/power/nsIDOMPowerManager.idl
@@ -37,17 +37,17 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMMozWakeLockListener;
 
 /**
  * This interface implements navigator.mozPower
  */
-[scriptable, uuid(4586bed1-cf78-4436-b503-88277d645b68)]
+[scriptable, uuid(256a3287-f528-45b5-9ba8-2b3650c056e6)]
 interface nsIDOMMozPowerManager : nsISupports
 {
     void    powerOff();
     void    reboot();
 
     /**
      * The listeners are notified when a resource changes its lock state to:
      *  - unlocked
@@ -91,9 +91,16 @@ interface nsIDOMMozPowerManager : nsISup
      * If you write a value of X into this attribute, the attribute may not have
      * the same value X when you later read it.  Most screens don't support as
      * many different brightness levels as there are doubles between 0 and 1, so
      * we may reduce the value's precision before storing it.
      *
      * @throw NS_ERROR_INVALID_ARG if brightness is not in the range [0, 1].
      */
     attribute double screenBrightness;
+
+    /**
+     * Is it possible that the device's CPU will sleep after the screen is
+     * disabled?  Setting this attribute to false will prevent the device
+     * entering suspend state.
+     */
+    attribute boolean cpuSleepAllowed;
 };
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -358,16 +358,32 @@ bool GetScreenEnabled()
 }
 
 void SetScreenEnabled(bool enabled)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(SetScreenEnabled(enabled));
 }
 
+bool GetCpuSleepAllowed()
+{
+  // Generally for interfaces that are accessible by normal web content
+  // we should cache the result and be notified on state changes, like
+  // what the battery API does. But since this is only used by
+  // privileged interface, the synchronous getter is OK here.
+  AssertMainThread();
+  RETURN_PROXY_IF_SANDBOXED(GetCpuSleepAllowed());
+}
+
+void SetCpuSleepAllowed(bool allowed)
+{
+  AssertMainThread();
+  PROXY_IF_SANDBOXED(SetCpuSleepAllowed(allowed));
+}
+
 double GetScreenBrightness()
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness());
 }
 
 void SetScreenBrightness(double brightness)
 {
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -144,16 +144,27 @@ double GetScreenBrightness();
  * Note that we may reduce the resolution of the given brightness value before
  * sending it to the screen.  Therefore if you call SetScreenBrightness(x)
  * followed by GetScreenBrightness(), the value returned by
  * GetScreenBrightness() may not be exactly x.
  */
 void SetScreenBrightness(double brightness);
 
 /**
+ * Determine whether the device is allowed to sleep.
+ */
+bool GetCpuSleepAllowed();
+
+/**
+ * Set whether the device is allowed to suspend automatically after
+ * the screen is disabled.
+ */
+void SetCpuSleepAllowed(bool allowed);
+
+/**
  * Set the value of a light to a particular color, with a specific flash pattern.
  * light specifices which light.  See Hal.idl for the list of constants
  * mode specifies user set or based on ambient light sensor
  * flash specifies whether or how to flash the light
  * flashOnMS and flashOffMS specify the pattern for XXX flash mode
  * color specifies the color.  If the light doesn't support color, the given color is
  * transformed into a brightness, or just an on/off if that is all the light is capable of.
  * returns true if successful and false if failed.
--- a/hal/Makefile.in
+++ b/hal/Makefile.in
@@ -112,17 +112,21 @@ CMMSRCS += \
 else
 CPPSRCS += \
   FallbackHal.cpp \
   FallbackSensor.cpp \
   $(NULL)
 endif
 
 ifneq (gonk,$(MOZ_WIDGET_TOOLKIT)) #{
-CPPSRCS += FallbackLights.cpp FallbackTime.cpp
+CPPSRCS += \
+  FallbackLights.cpp  \
+  FallbackTime.cpp \
+  FallbackWakeLocks.cpp \
+  $(NULL)
 endif #}
 
 # Screen Orientation backend
 ifneq (android,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += ScreenOrientationFallback.cpp
 endif
 
 include $(topsrcdir)/config/config.mk
new file mode 100644
--- /dev/null
+++ b/hal/fallback/FallbackWakeLocks.cpp
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* 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 "Hal.h"
+
+namespace mozilla {
+namespace hal_impl {
+
+bool
+GetCpuSleepAllowed()
+{
+  return true;
+}
+
+void
+SetCpuSleepAllowed(bool allowed)
+{}
+
+} // namespace hal_impl
+} // namespace mozilla
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -324,16 +324,18 @@ GetCurrentBatteryInformation(hal::Batter
 }
 
 namespace {
 
 /**
  * RAII class to help us remember to close file descriptors.
  */
 const char *screenEnabledFilename = "/sys/power/state";
+const char *wakeLockFilename = "/sys/power/wake_lock";
+const char *wakeUnlockFilename = "/sys/power/wake_unlock";
 
 template<ssize_t n>
 bool ReadFromFile(const char *filename, char (&buf)[n])
 {
   int fd = open(filename, O_RDONLY);
   ScopedClose autoClose(fd);
   if (fd < 0) {
     HAL_LOG(("Unable to open file %s.", filename));
@@ -365,16 +367,22 @@ void WriteToFile(const char *filename, c
   }
 }
 
 // We can write to screenEnabledFilename to enable/disable the screen, but when
 // we read, we always get "mem"!  So we have to keep track ourselves whether
 // the screen is on or not.
 bool sScreenEnabled = true;
 
+// We can read wakeLockFilename to find out whether the cpu wake lock
+// is already acquired, but reading and parsing it is a lot more work
+// than tracking it ourselves, and it won't be accurate anyway (kernel
+// internal wake locks aren't counted here.)
+bool sCpuSleepAllowed = true;
+
 } // anonymous namespace
 
 bool
 GetScreenEnabled()
 {
   return sScreenEnabled;
 }
 
@@ -417,16 +425,29 @@ SetScreenBrightness(double brightness)
   aConfig.mode() = hal::eHalLightMode_User;
   aConfig.flash() = hal::eHalLightFlash_None;
   aConfig.flashOnMS() = aConfig.flashOffMS() = 0;
   aConfig.color() = color;
   hal::SetLight(hal::eHalLightID_Backlight, aConfig);
   hal::SetLight(hal::eHalLightID_Buttons, aConfig);
 }
 
+bool
+GetCpuSleepAllowed()
+{
+  return sCpuSleepAllowed;
+}
+
+void
+SetCpuSleepAllowed(bool aAllowed)
+{
+  WriteToFile(aAllowed ? wakeUnlockFilename : wakeLockFilename, "gecko");
+  sCpuSleepAllowed = aAllowed;
+}
+
 static light_device_t* sLights[hal::eHalLightID_Count];	// will be initialized to NULL
 
 light_device_t* GetDevice(hw_module_t* module, char const* name)
 {
   int err;
   hw_device_t* device;
   err = module->methods->open(module, name, &device);
   if (err == 0) {
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -115,16 +115,19 @@ parent:
     EnableNetworkNotifications();
     DisableNetworkNotifications();
     sync GetCurrentNetworkInformation()
       returns (NetworkInformation aNetworkInfo);
 
     sync GetScreenEnabled() returns (bool enabled);
     SetScreenEnabled(bool enabled);
 
+    sync GetCpuSleepAllowed() returns (bool allowed);
+    SetCpuSleepAllowed(bool allowed);
+
     sync GetScreenBrightness() returns (double brightness);
     SetScreenBrightness(double brightness);
     
     AdjustSystemClock(int32 aDeltaMilliseconds);
     SetTimezone(nsCString aTimezoneSpec);
 
     sync SetLight(LightType light, LightConfiguration aConfig)
       returns (bool status);
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -133,16 +133,30 @@ GetScreenEnabled()
 }
 
 void
 SetScreenEnabled(bool enabled)
 {
   Hal()->SendSetScreenEnabled(enabled);
 }
 
+bool
+GetCpuSleepAllowed()
+{
+  bool allowed = true;
+  Hal()->SendGetCpuSleepAllowed(&allowed);
+  return allowed;
+}
+
+void
+SetCpuSleepAllowed(bool allowed)
+{
+  Hal()->SendSetCpuSleepAllowed(allowed);
+}
+
 double
 GetScreenBrightness()
 {
   double brightness = 0;
   Hal()->SendGetScreenBrightness(&brightness);
   return brightness;
 }
 
@@ -363,16 +377,30 @@ public:
   NS_OVERRIDE virtual bool
   RecvSetScreenEnabled(const bool &enabled)
   {
     hal::SetScreenEnabled(enabled);
     return true;
   }
 
   NS_OVERRIDE virtual bool
+  RecvGetCpuSleepAllowed(bool *allowed)
+  {
+    *allowed = hal::GetCpuSleepAllowed();
+    return true;
+  }
+
+  NS_OVERRIDE virtual bool
+  RecvSetCpuSleepAllowed(const bool &allowed)
+  {
+    hal::SetCpuSleepAllowed(allowed);
+    return true;
+  }
+
+  NS_OVERRIDE virtual bool
   RecvGetScreenBrightness(double *brightness)
   {
     *brightness = hal::GetScreenBrightness();
     return true;
   }
 
   NS_OVERRIDE virtual bool
   RecvSetScreenBrightness(const double &brightness)