Bug 714358: System time change implementation, r=mounir
authorSteven Lee <slee@mozilla.com>
Tue, 07 Aug 2012 19:20:00 -0400
changeset 107245 983f76488e59d6cda341d0441c2666acf4611aa1
parent 107244 7a92558a8dec5290a6f692801d73c144cad5ef3f
child 107246 5439489dc320dbe10c3826682983480b712039ae
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmounir
bugs714358
milestone17.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
@@ -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;
 }