Bug 714358: System time change implementation, r=mounir
authorSteven Lee <slee@mozilla.com>
Tue, 07 Aug 2012 19:20:00 -0400
changeset 104894 983f76488e59d6cda341d0441c2666acf4611aa1
parent 104893 7a92558a8dec5290a6f692801d73c144cad5ef3f
child 104895 5439489dc320dbe10c3826682983480b712039ae
push id1989
push userakeybl@mozilla.com
push dateTue, 28 Aug 2012 00:20:43 +0000
treeherdermozilla-aurora@a8e95ae10ea7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmounir
bugs714358
milestone17.0a1
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
@@ -3,10 +3,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 [scriptable, builtinclass, uuid(d29beaaa-bd54-4fd5-9f18-e0eedb1dc96d)]
 interface nsIDOMMozTimeManager : nsISupports
 {
   // jsval could be Date object or UTC seconds
-  void set(in jsval time);
+  [implicit_jscontext] void set(in jsval time);
 };
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -412,17 +412,38 @@ bool SetLight(LightType light, const hal
 }
 
 bool GetLight(LightType light, hal::LightConfiguration* aConfig)
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig));
 }
 
+static ObserverList<SystemTimeChange> sSystemTimeObserver;
 
+void
+RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  sSystemTimeObserver.AddObserver(aObserver);
+}
+
+void
+UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver)
+{
+  AssertMainThread();
+  sSystemTimeObserver.RemoveObserver(aObserver);
+}
+
+void
+NotifySystemTimeChange(const hal::SystemTimeChange& aReason)
+{
+  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
@@ -245,16 +247,34 @@ void AdjustSystemClock(int32_t aDeltaMil
 /**
  * Set timezone
  * @param aTimezoneSpec The definition can be found in 
  * http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  */
 void SetTimezone(const nsCString& aTimezoneSpec);
 
 /**
+ * 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
@@ -66,16 +66,23 @@ enum ProcessPriority {
  * Used by ModifyWakeLock
  */
 enum WakeLockControl {
   WAKE_LOCK_REMOVE_ONE = -1,
   WAKE_LOCK_NO_CHANGE  = 0,
   WAKE_LOCK_ADD_ONE    = 1,
 };
 
+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.
  */
@@ -138,12 +145,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,44 @@ 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);
+}
+
+bool
+IsSameTimeZone(const nsCString& aTimezoneSpec)
+{
+  char timezone[32];
+  property_get("persist.sys.timezone", timezone, "");
+  return aTimezoneSpec.EqualsASCII(timezone);
 }
 
 void 
 SetTimezone(const nsCString& aTimezoneSpec)
 { 
+  if (IsSameTimeZone(aTimezoneSpec)) {
+    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);
 }
 
 // Nothing to do here.  Gonk widgetry always listens for screen
 // orientation changes.
 void
 EnableScreenConfigurationNotifications()
 {
 }
--- 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
@@ -578,16 +578,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;
@@ -614,16 +619,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;
 }