Bug 714358 System time change implementation, r=mounir
authorSteven Lee <slee@mozilla.com>
Tue, 11 Sep 2012 02:40:00 -0400
changeset 113678 9efd6fc80405b40a892786f21fe3fe08c0de72a9
parent 113677 d059d752c212d0deecf1e7bd0a764bf51dce272d
child 113679 0a941f6df7f652e8161b5adadc6930ecb10c7955
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmounir
bugs714358
milestone18.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 714358 System time change implementation, r=mounir
dom/time/nsIDOMTimeManager.idl
hal/Hal.cpp
hal/Hal.h
hal/HalTypes.h
hal/gonk/GonkHal.cpp
hal/sandbox/PHal.ipdl
hal/sandbox/SandboxHal.cpp
--- a/dom/time/nsIDOMTimeManager.idl
+++ b/dom/time/nsIDOMTimeManager.idl
@@ -11,10 +11,10 @@ interface nsIDOMMozTimeManager : nsISupp
    *
    * The |time| argument can be either a Date object or a number.
    *
    * - If |time| is a number, it's interpreted as seconds since the epoch 
    *   (midnight UTC on January 1, 1970)
    * - If |time| is a Date object, |set(time)| is equivalent to 
    *   |set(time.getTime())|.
    */
-  void set(in jsval time);
+  [implicit_jscontext] void set(in jsval time);
 };
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -401,17 +401,49 @@ bool SetLight(LightType light, const hal
 }
 
 bool GetLight(LightType light, hal::LightConfiguration* aConfig)
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig));
 }
 
+static StaticAutoPtr<ObserverList<SystemTimeChange>> sSystemTimeObserver;
 
+static void
+InitializeSystemTimeChangeObserver()
+{
+  if (!sSystemTimeObserver) {
+    sSystemTimeObserver = new ObserverList<SystemTimeChange>;
+    ClearOnShutdown(&sSystemTimeObserver);
+  }
+}
+
+void
+RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  InitializeSystemTimeChangeObserver();
+  sSystemTimeObserver->AddObserver(aObserver);
+}
+
+void
+UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  sSystemTimeObserver->RemoveObserver(aObserver);
+}
+
+void
+NotifySystemTimeChange(const hal::SystemTimeChange& aReason)
+{
+  InitializeSystemTimeChangeObserver();
+  sSystemTimeObserver->Broadcast(aReason);
+}
+ 
 void 
 AdjustSystemClock(int32_t aDeltaMilliseconds)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds));
 }
 
 void 
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -45,16 +45,18 @@ namespace hal {
 typedef Observer<void_t> AlarmObserver;
 typedef Observer<ScreenConfiguration> ScreenConfigurationObserver;
 
 class WindowIdentifier;
 
 extern PRLogModuleInfo *sHalLog;
 #define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
 
+typedef Observer<SystemTimeChange> SystemTimeObserver;
+
 } // namespace hal
 
 namespace MOZ_HAL_NAMESPACE {
 
 /**
  * Turn the default vibrator device on/off per the pattern specified
  * by |pattern|.  Each element in the pattern is the number of
  * milliseconds to turn the vibrator on or off.  The first element in
@@ -251,16 +253,34 @@ void SetTimezone(const nsCString& aTimez
 
 /**
  * Get timezone
  * http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  */
 nsCString GetTimezone();
 
 /**
+ * Register observer for system time changed notification.
+ * @param aObserver The observer that should be added.
+ */
+void RegisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
+
+/**
+ * Unregister the observer for system time changed.
+ * @param aObserver The observer that should be removed.
+ */
+void UnregisterSystemTimeChangeObserver(hal::SystemTimeObserver* aObserver);
+
+/**
+ * Notify of a change in the system cloeck or time zone.
+ * @param aReason
+ */
+void NotifySystemTimeChange(const hal::SystemTimeChange& aReason);
+
+/**
  * Reboot the device.
  */
 void Reboot();
 
 /**
  * Power off the device.
  */
 void PowerOff();
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -69,16 +69,23 @@ enum ProcessPriority {
  */
 enum WakeLockControl {
   WAKE_LOCK_REMOVE_ONE = -1,
   WAKE_LOCK_NO_CHANGE  = 0,
   WAKE_LOCK_ADD_ONE    = 1,
   NUM_WAKE_LOCK
 };
 
+enum SystemTimeChange {
+  SYS_TIME_CHANGE_UNKNOWN = -1,
+  SYS_TIME_CHANGE_CLOCK,
+  SYS_TIME_CHANGE_TZ,
+  SYS_TIME_CHANGE_GUARD
+};
+
 } // namespace hal
 } // namespace mozilla
 
 namespace IPC {
 
 /**
  * Light type serializer.
  */
@@ -141,12 +148,21 @@ struct ParamTraits<mozilla::hal::SwitchD
 
 template <>
 struct ParamTraits<mozilla::hal::ProcessPriority>:
   public EnumSerializer<mozilla::hal::ProcessPriority,
                         mozilla::hal::PROCESS_PRIORITY_BACKGROUND,
                         mozilla::hal::NUM_PROCESS_PRIORITY> {
 };
 
-
+/**
+ * SystemTimeChange serializer.
+ */
+template <>
+struct ParamTraits<mozilla::hal::SystemTimeChange>
+  : public EnumSerializer<mozilla::hal::SystemTimeChange,
+                          mozilla::hal::SYS_TIME_CHANGE_UNKNOWN,
+                          mozilla::hal::SYS_TIME_CHANGE_GUARD>
+{};
+ 
 } // namespace IPC
 
 #endif // mozilla_hal_Types_h
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -576,16 +576,20 @@ static int
 sys_clock_settime(clockid_t clk_id, const struct timespec *tp)
 {
   return syscall(__NR_clock_settime, clk_id, tp);
 }
 
 void 
 AdjustSystemClock(int32_t aDeltaMilliseconds)
 {
+  if (aDeltaMilliseconds == 0) {
+    return;
+  }
+  
   struct timespec now;
   
   // Preventing context switch before setting system clock 
   sched_yield();
   clock_gettime(CLOCK_REALTIME, &now);
   now.tv_sec += aDeltaMilliseconds/1000;
   now.tv_nsec += (aDeltaMilliseconds%1000)*NsecPerMsec;
   if (now.tv_nsec >= NsecPerSec)
@@ -595,26 +599,36 @@ AdjustSystemClock(int32_t aDeltaMillisec
   }
 
   if (now.tv_nsec < 0)
   {
     now.tv_nsec += NsecPerSec;
     now.tv_sec -= 1;  
   }
   // we need to have root privilege. 
-  sys_clock_settime(CLOCK_REALTIME, &now);   
+  if (sys_clock_settime(CLOCK_REALTIME, &now) != 0) {
+    NS_ERROR("sys_clock_settime failed");
+    return;
+  }
+  
+  hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK);
 }
 
 void 
 SetTimezone(const nsCString& aTimezoneSpec)
-{ 
+{
+  if (aTimezoneSpec.Equals(GetTimezone())) {
+    return;
+  }
+
   property_set("persist.sys.timezone", aTimezoneSpec.get());
   // this function is automatically called by the other time conversion 
   // functions that depend on the timezone. To be safe, we call it manually.  
   tzset();
+  hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_TZ);
 }
 
 nsCString 
 GetTimezone()
 {
   char timezone[32];
   property_get("persist.sys.timezone", timezone, "");
   return nsCString(timezone);
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -19,16 +19,17 @@ using mozilla::hal::LightMode;
 using mozilla::hal::SensorType;
 using mozilla::hal::SensorAccuracyType;
 using mozilla::hal::WakeLockControl;
 using mozilla::hal::SwitchState;
 using mozilla::hal::SwitchDevice;
 using mozilla::hal::ProcessPriority;
 using nsIntRect;
 using PRTime;
+using mozilla::hal::SystemTimeChange;
 
 namespace mozilla {
 
 namespace hal {
 struct BatteryInformation {
   double level;
   bool   charging;
   double remainingTime;
@@ -81,16 +82,17 @@ sync protocol PHal {
     manager PContent;
 
 child:
     NotifyBatteryChange(BatteryInformation aBatteryInfo);
     NotifyNetworkChange(NetworkInformation aNetworkInfo);
     NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
     NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation);
     NotifySwitchChange(SwitchEvent aEvent);
+    NotifySystemTimeChange(SystemTimeChange aReason); 
 
 parent:
     Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser);
     CancelVibrate(uint64_t[] id, PBrowser browser);
 
     EnableBatteryNotifications();
     DisableBatteryNotifications();
     sync GetCurrentBatteryInformation()
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -671,16 +671,21 @@ public:
   virtual bool
   RecvSetProcessPriority(const int& aPid, const ProcessPriority& aPriority)
   {
     // TODO As a security check, we should ensure that aPid is either the pid
     // of our child, or the pid of one of the child's children.
     hal::SetProcessPriority(aPid, aPriority);
     return true;
   }
+
+  void Notify(const SystemTimeChange& aReason)
+  {
+    unused << SendNotifySystemTimeChange(aReason);
+  }
 };
 
 class HalChild : public PHalChild {
 public:
   virtual bool
   RecvNotifyBatteryChange(const BatteryInformation& aBatteryInfo) MOZ_OVERRIDE {
     hal::NotifyBatteryChange(aBatteryInfo);
     return true;
@@ -707,16 +712,22 @@ public:
     return true;
   }
 
   virtual bool
   RecvNotifySwitchChange(const mozilla::hal::SwitchEvent& aEvent) MOZ_OVERRIDE {
     hal::NotifySwitchChange(aEvent);
     return true;
   }
+
+  virtual bool
+  RecvNotifySystemTimeChange(const SystemTimeChange& aReason) {
+    hal::NotifySystemTimeChange(aReason);
+    return true;
+  }
 };
 
 bool
 HalChild::RecvNotifySensorChange(const hal::SensorData &aSensorData) {
   hal::NotifySensorChange(aSensorData);
   
   return true;
 }