hal/Hal.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et ft=cpp : */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "Hal.h"
     8 #include "HalImpl.h"
     9 #include "HalSandbox.h"
    10 #include "nsThreadUtils.h"
    11 #include "nsXULAppAPI.h"
    12 #include "mozilla/Observer.h"
    13 #include "nsIDocument.h"
    14 #include "nsIDOMDocument.h"
    15 #include "nsPIDOMWindow.h"
    16 #include "nsIDOMWindow.h"
    17 #include "mozilla/Services.h"
    18 #include "nsIWebNavigation.h"
    19 #include "nsITabChild.h"
    20 #include "nsIDocShell.h"
    21 #include "mozilla/StaticPtr.h"
    22 #include "mozilla/ClearOnShutdown.h"
    23 #include "WindowIdentifier.h"
    24 #include "mozilla/dom/ScreenOrientation.h"
    25 #include "mozilla/dom/ContentChild.h"
    26 #include "mozilla/dom/ContentParent.h"
    28 #ifdef XP_WIN
    29 #include <process.h>
    30 #define getpid _getpid
    31 #endif
    33 using namespace mozilla::services;
    34 using namespace mozilla::dom;
    36 #define PROXY_IF_SANDBOXED(_call)                 \
    37   do {                                            \
    38     if (InSandbox()) {                            \
    39       if (!hal_sandbox::HalChildDestroyed()) {    \
    40         hal_sandbox::_call;                       \
    41       }                                           \
    42     } else {                                      \
    43       hal_impl::_call;                            \
    44     }                                             \
    45   } while (0)
    47 #define RETURN_PROXY_IF_SANDBOXED(_call, defValue)\
    48   do {                                            \
    49     if (InSandbox()) {                            \
    50       if (hal_sandbox::HalChildDestroyed()) {     \
    51         return defValue;                          \
    52       }                                           \
    53       return hal_sandbox::_call;                  \
    54     } else {                                      \
    55       return hal_impl::_call;                     \
    56     }                                             \
    57   } while (0)
    59 namespace mozilla {
    60 namespace hal {
    62 PRLogModuleInfo *
    63 GetHalLog()
    64 {
    65   static PRLogModuleInfo *sHalLog;
    66   if (!sHalLog) {
    67     sHalLog = PR_NewLogModule("hal");
    68   }
    69   return sHalLog;
    70 }
    72 namespace {
    74 void
    75 AssertMainThread()
    76 {
    77   MOZ_ASSERT(NS_IsMainThread());
    78 }
    80 bool
    81 InSandbox()
    82 {
    83   return GeckoProcessType_Content == XRE_GetProcessType();
    84 }
    86 void
    87 AssertMainProcess()
    88 {
    89   MOZ_ASSERT(GeckoProcessType_Default == XRE_GetProcessType());
    90 }
    92 bool
    93 WindowIsActive(nsIDOMWindow* aWindow)
    94 {
    95   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
    96   NS_ENSURE_TRUE(window, false);
    98   nsIDocument* document = window->GetDoc();
    99   NS_ENSURE_TRUE(document, false);
   101   return !document->Hidden();
   102 }
   104 StaticAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
   106 void InitLastIDToVibrate()
   107 {
   108   gLastIDToVibrate = new WindowIdentifier::IDArrayType();
   109   ClearOnShutdown(&gLastIDToVibrate);
   110 }
   112 } // anonymous namespace
   114 void
   115 Vibrate(const nsTArray<uint32_t>& pattern, nsIDOMWindow* window)
   116 {
   117   Vibrate(pattern, WindowIdentifier(window));
   118 }
   120 void
   121 Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id)
   122 {
   123   AssertMainThread();
   125   // Only active windows may start vibrations.  If |id| hasn't gone
   126   // through the IPC layer -- that is, if our caller is the outside
   127   // world, not hal_proxy -- check whether the window is active.  If
   128   // |id| has gone through IPC, don't check the window's visibility;
   129   // only the window corresponding to the bottommost process has its
   130   // visibility state set correctly.
   131   if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
   132     HAL_LOG(("Vibrate: Window is inactive, dropping vibrate."));
   133     return;
   134   }
   136   if (!InSandbox()) {
   137     if (!gLastIDToVibrate) {
   138       InitLastIDToVibrate();
   139     }
   140     *gLastIDToVibrate = id.AsArray();
   141   }
   143   // Don't forward our ID if we are not in the sandbox, because hal_impl 
   144   // doesn't need it, and we don't want it to be tempted to read it.  The
   145   // empty identifier will assert if it's used.
   146   PROXY_IF_SANDBOXED(Vibrate(pattern, InSandbox() ? id : WindowIdentifier()));
   147 }
   149 void
   150 CancelVibrate(nsIDOMWindow* window)
   151 {
   152   CancelVibrate(WindowIdentifier(window));
   153 }
   155 void
   156 CancelVibrate(const WindowIdentifier &id)
   157 {
   158   AssertMainThread();
   160   // Although only active windows may start vibrations, a window may
   161   // cancel its own vibration even if it's no longer active.
   162   //
   163   // After a window is marked as inactive, it sends a CancelVibrate
   164   // request.  We want this request to cancel a playing vibration
   165   // started by that window, so we certainly don't want to reject the
   166   // cancellation request because the window is now inactive.
   167   //
   168   // But it could be the case that, after this window became inactive,
   169   // some other window came along and started a vibration.  We don't
   170   // want this window's cancellation request to cancel that window's
   171   // actively-playing vibration!
   172   //
   173   // To solve this problem, we keep track of the id of the last window
   174   // to start a vibration, and only accepts cancellation requests from
   175   // the same window.  All other cancellation requests are ignored.
   177   if (InSandbox() || (gLastIDToVibrate && *gLastIDToVibrate == id.AsArray())) {
   178     // Don't forward our ID if we are not in the sandbox, because hal_impl 
   179     // doesn't need it, and we don't want it to be tempted to read it.  The
   180     // empty identifier will assert if it's used.
   181     PROXY_IF_SANDBOXED(CancelVibrate(InSandbox() ? id : WindowIdentifier()));
   182   }
   183 }
   185 template <class InfoType>
   186 class ObserversManager
   187 {
   188 public:
   189   void AddObserver(Observer<InfoType>* aObserver) {
   190     if (!mObservers) {
   191       mObservers = new mozilla::ObserverList<InfoType>();
   192     }
   194     mObservers->AddObserver(aObserver);
   196     if (mObservers->Length() == 1) {
   197       EnableNotifications();
   198     }
   199   }
   201   void RemoveObserver(Observer<InfoType>* aObserver) {
   202     bool removed = mObservers && mObservers->RemoveObserver(aObserver);
   203     if (!removed) {
   204       NS_WARNING("RemoveObserver() called for unregistered observer");
   205       return;
   206     }
   208     if (mObservers->Length() == 0) {
   209       DisableNotifications();
   211       OnNotificationsDisabled();
   213       delete mObservers;
   214       mObservers = nullptr;
   215     }
   216   }
   218   void BroadcastInformation(const InfoType& aInfo) {
   219     // It is possible for mObservers to be nullptr here on some platforms,
   220     // because a call to BroadcastInformation gets queued up asynchronously
   221     // while RemoveObserver is running (and before the notifications are
   222     // disabled). The queued call can then get run after mObservers has
   223     // been nulled out. See bug 757025.
   224     if (!mObservers) {
   225       return;
   226     }
   227     mObservers->Broadcast(aInfo);
   228   }
   230 protected:
   231   virtual void EnableNotifications() = 0;
   232   virtual void DisableNotifications() = 0;
   233   virtual void OnNotificationsDisabled() {}
   235 private:
   236   mozilla::ObserverList<InfoType>* mObservers;
   237 };
   239 template <class InfoType>
   240 class CachingObserversManager : public ObserversManager<InfoType>
   241 {
   242 public:
   243   InfoType GetCurrentInformation() {
   244     if (mHasValidCache) {
   245       return mInfo;
   246     }
   248     GetCurrentInformationInternal(&mInfo);
   249     mHasValidCache = true;
   250     return mInfo;
   251   }
   253   void CacheInformation(const InfoType& aInfo) {
   254     mHasValidCache = true;
   255     mInfo = aInfo;
   256   }
   258   void BroadcastCachedInformation() {
   259     this->BroadcastInformation(mInfo);
   260   }
   262 protected:
   263   virtual void GetCurrentInformationInternal(InfoType*) = 0;
   265   virtual void OnNotificationsDisabled() {
   266     mHasValidCache = false;
   267   }
   269 private:
   270   InfoType                mInfo;
   271   bool                    mHasValidCache;
   272 };
   274 class BatteryObserversManager : public CachingObserversManager<BatteryInformation>
   275 {
   276 protected:
   277   void EnableNotifications() {
   278     PROXY_IF_SANDBOXED(EnableBatteryNotifications());
   279   }
   281   void DisableNotifications() {
   282     PROXY_IF_SANDBOXED(DisableBatteryNotifications());
   283   }
   285   void GetCurrentInformationInternal(BatteryInformation* aInfo) {
   286     PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo));
   287   }
   288 };
   290 static BatteryObserversManager sBatteryObservers;
   292 class NetworkObserversManager : public CachingObserversManager<NetworkInformation>
   293 {
   294 protected:
   295   void EnableNotifications() {
   296     PROXY_IF_SANDBOXED(EnableNetworkNotifications());
   297   }
   299   void DisableNotifications() {
   300     PROXY_IF_SANDBOXED(DisableNetworkNotifications());
   301   }
   303   void GetCurrentInformationInternal(NetworkInformation* aInfo) {
   304     PROXY_IF_SANDBOXED(GetCurrentNetworkInformation(aInfo));
   305   }
   306 };
   308 static NetworkObserversManager sNetworkObservers;
   310 class WakeLockObserversManager : public ObserversManager<WakeLockInformation>
   311 {
   312 protected:
   313   void EnableNotifications() {
   314     PROXY_IF_SANDBOXED(EnableWakeLockNotifications());
   315   }
   317   void DisableNotifications() {
   318     PROXY_IF_SANDBOXED(DisableWakeLockNotifications());
   319   }
   320 };
   322 static WakeLockObserversManager sWakeLockObservers;
   324 class ScreenConfigurationObserversManager : public CachingObserversManager<ScreenConfiguration>
   325 {
   326 protected:
   327   void EnableNotifications() {
   328     PROXY_IF_SANDBOXED(EnableScreenConfigurationNotifications());
   329   }
   331   void DisableNotifications() {
   332     PROXY_IF_SANDBOXED(DisableScreenConfigurationNotifications());
   333   }
   335   void GetCurrentInformationInternal(ScreenConfiguration* aInfo) {
   336     PROXY_IF_SANDBOXED(GetCurrentScreenConfiguration(aInfo));
   337   }
   338 };
   340 static ScreenConfigurationObserversManager sScreenConfigurationObservers;
   342 void
   343 RegisterBatteryObserver(BatteryObserver* aObserver)
   344 {
   345   AssertMainThread();
   346   sBatteryObservers.AddObserver(aObserver);
   347 }
   349 void
   350 UnregisterBatteryObserver(BatteryObserver* aObserver)
   351 {
   352   AssertMainThread();
   353   sBatteryObservers.RemoveObserver(aObserver);
   354 }
   356 void
   357 GetCurrentBatteryInformation(BatteryInformation* aInfo)
   358 {
   359   AssertMainThread();
   360   *aInfo = sBatteryObservers.GetCurrentInformation();
   361 }
   363 void
   364 NotifyBatteryChange(const BatteryInformation& aInfo)
   365 {
   366   AssertMainThread();
   367   sBatteryObservers.CacheInformation(aInfo);
   368   sBatteryObservers.BroadcastCachedInformation();
   369 }
   371 bool GetScreenEnabled()
   372 {
   373   AssertMainThread();
   374   RETURN_PROXY_IF_SANDBOXED(GetScreenEnabled(), false);
   375 }
   377 void SetScreenEnabled(bool enabled)
   378 {
   379   AssertMainThread();
   380   PROXY_IF_SANDBOXED(SetScreenEnabled(enabled));
   381 }
   383 bool GetCpuSleepAllowed()
   384 {
   385   // Generally for interfaces that are accessible by normal web content
   386   // we should cache the result and be notified on state changes, like
   387   // what the battery API does. But since this is only used by
   388   // privileged interface, the synchronous getter is OK here.
   389   AssertMainThread();
   390   RETURN_PROXY_IF_SANDBOXED(GetCpuSleepAllowed(), true);
   391 }
   393 void SetCpuSleepAllowed(bool allowed)
   394 {
   395   AssertMainThread();
   396   PROXY_IF_SANDBOXED(SetCpuSleepAllowed(allowed));
   397 }
   399 double GetScreenBrightness()
   400 {
   401   AssertMainThread();
   402   RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness(), 0);
   403 }
   405 void SetScreenBrightness(double brightness)
   406 {
   407   AssertMainThread();
   408   PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(brightness, 0.0, 1.0)));
   409 }
   411 bool SetLight(LightType light, const LightConfiguration& aConfig)
   412 {
   413   AssertMainThread();
   414   RETURN_PROXY_IF_SANDBOXED(SetLight(light, aConfig), false);
   415 }
   417 bool GetLight(LightType light, LightConfiguration* aConfig)
   418 {
   419   AssertMainThread();
   420   RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig), false);
   421 }
   423 class SystemClockChangeObserversManager : public ObserversManager<int64_t>
   424 {
   425 protected:
   426   void EnableNotifications() {
   427     PROXY_IF_SANDBOXED(EnableSystemClockChangeNotifications());
   428   }
   430   void DisableNotifications() {
   431     PROXY_IF_SANDBOXED(DisableSystemClockChangeNotifications());
   432   }
   433 };
   435 static SystemClockChangeObserversManager sSystemClockChangeObservers;
   437 void
   438 RegisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver)
   439 {
   440   AssertMainThread();
   441   sSystemClockChangeObservers.AddObserver(aObserver);
   442 }
   444 void
   445 UnregisterSystemClockChangeObserver(SystemClockChangeObserver* aObserver)
   446 {
   447   AssertMainThread();
   448   sSystemClockChangeObservers.RemoveObserver(aObserver);
   449 }
   451 void
   452 NotifySystemClockChange(const int64_t& aClockDeltaMS)
   453 {
   454   sSystemClockChangeObservers.BroadcastInformation(aClockDeltaMS);
   455 }
   457 class SystemTimezoneChangeObserversManager : public ObserversManager<SystemTimezoneChangeInformation>
   458 {
   459 protected:
   460   void EnableNotifications() {
   461     PROXY_IF_SANDBOXED(EnableSystemTimezoneChangeNotifications());
   462   }
   464   void DisableNotifications() {
   465     PROXY_IF_SANDBOXED(DisableSystemTimezoneChangeNotifications());
   466   }
   467 };
   469 static SystemTimezoneChangeObserversManager sSystemTimezoneChangeObservers;
   471 void
   472 RegisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver)
   473 {
   474   AssertMainThread();
   475   sSystemTimezoneChangeObservers.AddObserver(aObserver);
   476 }
   478 void
   479 UnregisterSystemTimezoneChangeObserver(SystemTimezoneChangeObserver* aObserver)
   480 {
   481   AssertMainThread();
   482   sSystemTimezoneChangeObservers.RemoveObserver(aObserver);
   483 }
   485 void
   486 NotifySystemTimezoneChange(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
   487 {
   488   sSystemTimezoneChangeObservers.BroadcastInformation(aSystemTimezoneChangeInfo);
   489 }
   491 void 
   492 AdjustSystemClock(int64_t aDeltaMilliseconds)
   493 {
   494   AssertMainThread();
   495   PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds));
   496 }
   498 void 
   499 SetTimezone(const nsCString& aTimezoneSpec)
   500 {
   501   AssertMainThread();
   502   PROXY_IF_SANDBOXED(SetTimezone(aTimezoneSpec));
   503 }
   505 int32_t
   506 GetTimezoneOffset()
   507 {
   508   AssertMainThread();
   509   RETURN_PROXY_IF_SANDBOXED(GetTimezoneOffset(), 0);
   510 }
   512 nsCString
   513 GetTimezone()
   514 {
   515   AssertMainThread();
   516   RETURN_PROXY_IF_SANDBOXED(GetTimezone(), nsCString(""));
   517 }
   519 void
   520 EnableSensorNotifications(SensorType aSensor) {
   521   AssertMainThread();
   522   PROXY_IF_SANDBOXED(EnableSensorNotifications(aSensor));
   523 }
   525 void
   526 DisableSensorNotifications(SensorType aSensor) {
   527   AssertMainThread();
   528   PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor));
   529 }
   531 typedef mozilla::ObserverList<SensorData> SensorObserverList;
   532 static SensorObserverList* gSensorObservers = nullptr;
   534 static SensorObserverList &
   535 GetSensorObservers(SensorType sensor_type) {
   536   MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE);
   538   if(!gSensorObservers) {
   539     gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE];
   540   }
   541   return gSensorObservers[sensor_type];
   542 }
   544 void
   545 RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
   546   SensorObserverList &observers = GetSensorObservers(aSensor);
   548   AssertMainThread();
   550   observers.AddObserver(aObserver);
   551   if(observers.Length() == 1) {
   552     EnableSensorNotifications(aSensor);
   553   }
   554 }
   556 void
   557 UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
   558   AssertMainThread();
   560   if (!gSensorObservers) {
   561     return;
   562   }
   564   SensorObserverList &observers = GetSensorObservers(aSensor);
   565   if (!observers.RemoveObserver(aObserver) || observers.Length() > 0) {
   566     return;
   567   }
   568   DisableSensorNotifications(aSensor);
   570   // Destroy sSensorObservers only if all observer lists are empty.
   571   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
   572     if (gSensorObservers[i].Length() > 0) {
   573       return;
   574     }
   575   }
   576   delete [] gSensorObservers;
   577   gSensorObservers = nullptr;
   578 }
   580 void
   581 NotifySensorChange(const SensorData &aSensorData) {
   582   SensorObserverList &observers = GetSensorObservers(aSensorData.sensor());
   584   AssertMainThread();
   586   observers.Broadcast(aSensorData);
   587 }
   589 void
   590 RegisterNetworkObserver(NetworkObserver* aObserver)
   591 {
   592   AssertMainThread();
   593   sNetworkObservers.AddObserver(aObserver);
   594 }
   596 void
   597 UnregisterNetworkObserver(NetworkObserver* aObserver)
   598 {
   599   AssertMainThread();
   600   sNetworkObservers.RemoveObserver(aObserver);
   601 }
   603 void
   604 GetCurrentNetworkInformation(NetworkInformation* aInfo)
   605 {
   606   AssertMainThread();
   607   *aInfo = sNetworkObservers.GetCurrentInformation();
   608 }
   610 void
   611 NotifyNetworkChange(const NetworkInformation& aInfo)
   612 {
   613   sNetworkObservers.CacheInformation(aInfo);
   614   sNetworkObservers.BroadcastCachedInformation();
   615 }
   617 void Reboot()
   618 {
   619   AssertMainProcess();
   620   AssertMainThread();
   621   PROXY_IF_SANDBOXED(Reboot());
   622 }
   624 void PowerOff()
   625 {
   626   AssertMainProcess();
   627   AssertMainThread();
   628   PROXY_IF_SANDBOXED(PowerOff());
   629 }
   631 void StartForceQuitWatchdog(ShutdownMode aMode, int32_t aTimeoutSecs)
   632 {
   633   AssertMainProcess();
   634   AssertMainThread();
   635   PROXY_IF_SANDBOXED(StartForceQuitWatchdog(aMode, aTimeoutSecs));
   636 }
   638 void StartMonitoringGamepadStatus()
   639 {
   640   PROXY_IF_SANDBOXED(StartMonitoringGamepadStatus());
   641 }
   643 void StopMonitoringGamepadStatus()
   644 {
   645   PROXY_IF_SANDBOXED(StopMonitoringGamepadStatus());
   646 }
   648 void
   649 RegisterWakeLockObserver(WakeLockObserver* aObserver)
   650 {
   651   AssertMainThread();
   652   sWakeLockObservers.AddObserver(aObserver);
   653 }
   655 void
   656 UnregisterWakeLockObserver(WakeLockObserver* aObserver)
   657 {
   658   AssertMainThread();
   659   sWakeLockObservers.RemoveObserver(aObserver);
   660 }
   662 void
   663 ModifyWakeLock(const nsAString& aTopic,
   664                WakeLockControl aLockAdjust,
   665                WakeLockControl aHiddenAdjust,
   666                uint64_t aProcessID /* = CONTENT_PROCESS_ID_UNKNOWN */)
   667 {
   668   AssertMainThread();
   670   if (aProcessID == CONTENT_PROCESS_ID_UNKNOWN) {
   671     aProcessID = InSandbox() ? ContentChild::GetSingleton()->GetID() :
   672                                CONTENT_PROCESS_ID_MAIN;
   673   }
   675   PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust,
   676                                     aHiddenAdjust, aProcessID));
   677 }
   679 void
   680 GetWakeLockInfo(const nsAString& aTopic, WakeLockInformation* aWakeLockInfo)
   681 {
   682   AssertMainThread();
   683   PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo));
   684 }
   686 void
   687 NotifyWakeLockChange(const WakeLockInformation& aInfo)
   688 {
   689   AssertMainThread();
   690   sWakeLockObservers.BroadcastInformation(aInfo);
   691 }
   693 void
   694 RegisterScreenConfigurationObserver(ScreenConfigurationObserver* aObserver)
   695 {
   696   AssertMainThread();
   697   sScreenConfigurationObservers.AddObserver(aObserver);
   698 }
   700 void
   701 UnregisterScreenConfigurationObserver(ScreenConfigurationObserver* aObserver)
   702 {
   703   AssertMainThread();
   704   sScreenConfigurationObservers.RemoveObserver(aObserver);
   705 }
   707 void
   708 GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration)
   709 {
   710   AssertMainThread();
   711   *aScreenConfiguration = sScreenConfigurationObservers.GetCurrentInformation();
   712 }
   714 void
   715 NotifyScreenConfigurationChange(const ScreenConfiguration& aScreenConfiguration)
   716 {
   717   sScreenConfigurationObservers.CacheInformation(aScreenConfiguration);
   718   sScreenConfigurationObservers.BroadcastCachedInformation();
   719 }
   721 bool
   722 LockScreenOrientation(const dom::ScreenOrientation& aOrientation)
   723 {
   724   AssertMainThread();
   725   RETURN_PROXY_IF_SANDBOXED(LockScreenOrientation(aOrientation), false);
   726 }
   728 void
   729 UnlockScreenOrientation()
   730 {
   731   AssertMainThread();
   732   PROXY_IF_SANDBOXED(UnlockScreenOrientation());
   733 }
   735 void
   736 EnableSwitchNotifications(SwitchDevice aDevice) {
   737   AssertMainThread();
   738   PROXY_IF_SANDBOXED(EnableSwitchNotifications(aDevice));
   739 }
   741 void
   742 DisableSwitchNotifications(SwitchDevice aDevice) {
   743   AssertMainThread();
   744   PROXY_IF_SANDBOXED(DisableSwitchNotifications(aDevice));
   745 }
   747 SwitchState GetCurrentSwitchState(SwitchDevice aDevice)
   748 {
   749   AssertMainThread();
   750   RETURN_PROXY_IF_SANDBOXED(GetCurrentSwitchState(aDevice), SWITCH_STATE_UNKNOWN);
   751 }
   753 void NotifySwitchStateFromInputDevice(SwitchDevice aDevice, SwitchState aState)
   754 {
   755   PROXY_IF_SANDBOXED(NotifySwitchStateFromInputDevice(aDevice, aState));
   756 }
   758 typedef mozilla::ObserverList<SwitchEvent> SwitchObserverList;
   760 static SwitchObserverList *sSwitchObserverLists = nullptr;
   762 static SwitchObserverList&
   763 GetSwitchObserverList(SwitchDevice aDevice) {
   764   MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); 
   765   if (sSwitchObserverLists == nullptr) {
   766     sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE];
   767   }
   768   return sSwitchObserverLists[aDevice];
   769 }
   771 static void
   772 ReleaseObserversIfNeeded() {
   773   for (int i = 0; i < NUM_SWITCH_DEVICE; i++) {
   774     if (sSwitchObserverLists[i].Length() != 0)
   775       return;
   776   }
   778   //The length of every list is 0, no observer in the list.
   779   delete [] sSwitchObserverLists;
   780   sSwitchObserverLists = nullptr;
   781 }
   783 void
   784 RegisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
   785 {
   786   AssertMainThread();
   787   SwitchObserverList& observer = GetSwitchObserverList(aDevice);
   788   observer.AddObserver(aObserver);
   789   if (observer.Length() == 1) {
   790     EnableSwitchNotifications(aDevice);
   791   }
   792 }
   794 void
   795 UnregisterSwitchObserver(SwitchDevice aDevice, SwitchObserver *aObserver)
   796 {
   797   AssertMainThread();
   799   if (!sSwitchObserverLists) {
   800     return;
   801   }
   803   SwitchObserverList& observer = GetSwitchObserverList(aDevice);
   804   if (!observer.RemoveObserver(aObserver) || observer.Length() > 0) {
   805     return;
   806   }
   808   DisableSwitchNotifications(aDevice);
   809   ReleaseObserversIfNeeded();
   810 }
   812 void
   813 NotifySwitchChange(const SwitchEvent& aEvent)
   814 {
   815   // When callback this notification, main thread may call unregister function
   816   // first. We should check if this pointer is valid.
   817   if (!sSwitchObserverLists)
   818     return;
   820   SwitchObserverList& observer = GetSwitchObserverList(aEvent.device());
   821   observer.Broadcast(aEvent);
   822 }
   824 static AlarmObserver* sAlarmObserver;
   826 bool
   827 RegisterTheOneAlarmObserver(AlarmObserver* aObserver)
   828 {
   829   MOZ_ASSERT(!InSandbox());
   830   MOZ_ASSERT(!sAlarmObserver);
   832   sAlarmObserver = aObserver;
   833   RETURN_PROXY_IF_SANDBOXED(EnableAlarm(), false);
   834 }
   836 void
   837 UnregisterTheOneAlarmObserver()
   838 {
   839   if (sAlarmObserver) {
   840     sAlarmObserver = nullptr;
   841     PROXY_IF_SANDBOXED(DisableAlarm());
   842   }
   843 }
   845 void
   846 NotifyAlarmFired()
   847 {
   848   if (sAlarmObserver) {
   849     sAlarmObserver->Notify(void_t());
   850   }
   851 }
   853 bool
   854 SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
   855 {
   856   // It's pointless to program an alarm nothing is going to observe ...
   857   MOZ_ASSERT(sAlarmObserver);
   858   RETURN_PROXY_IF_SANDBOXED(SetAlarm(aSeconds, aNanoseconds), false);
   859 }
   861 void
   862 SetProcessPriority(int aPid,
   863                    ProcessPriority aPriority,
   864                    ProcessCPUPriority aCPUPriority,
   865                    uint32_t aBackgroundLRU)
   866 {
   867   // n.b. The sandboxed implementation crashes; SetProcessPriority works only
   868   // from the main process.
   869   MOZ_ASSERT(aBackgroundLRU == 0 || aPriority == PROCESS_PRIORITY_BACKGROUND);
   870   PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aCPUPriority,
   871                                         aBackgroundLRU));
   872 }
   874 // From HalTypes.h.
   875 const char*
   876 ProcessPriorityToString(ProcessPriority aPriority)
   877 {
   878   switch (aPriority) {
   879   case PROCESS_PRIORITY_MASTER:
   880     return "MASTER";
   881   case PROCESS_PRIORITY_PREALLOC:
   882     return "PREALLOC";
   883   case PROCESS_PRIORITY_FOREGROUND_HIGH:
   884     return "FOREGROUND_HIGH";
   885   case PROCESS_PRIORITY_FOREGROUND:
   886     return "FOREGROUND";
   887   case PROCESS_PRIORITY_FOREGROUND_KEYBOARD:
   888     return "FOREGROUND_KEYBOARD";
   889   case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE:
   890     return "BACKGROUND_PERCEIVABLE";
   891   case PROCESS_PRIORITY_BACKGROUND_HOMESCREEN:
   892     return "BACKGROUND_HOMESCREEN";
   893   case PROCESS_PRIORITY_BACKGROUND:
   894     return "BACKGROUND";
   895   case PROCESS_PRIORITY_UNKNOWN:
   896     return "UNKNOWN";
   897   default:
   898     MOZ_ASSERT(false);
   899     return "???";
   900   }
   901 }
   903 // From HalTypes.h.
   904 const char*
   905 ProcessPriorityToString(ProcessPriority aPriority,
   906                         ProcessCPUPriority aCPUPriority)
   907 {
   908   // Sorry this is ugly.  At least it's all in one place.
   909   //
   910   // We intentionally fall through if aCPUPriority is invalid; we won't hit any
   911   // of the if statements further down, so it's OK.
   913   switch (aPriority) {
   914   case PROCESS_PRIORITY_MASTER:
   915     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   916       return "MASTER:CPU_NORMAL";
   917     }
   918     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   919       return "MASTER:CPU_LOW";
   920     }
   921   case PROCESS_PRIORITY_PREALLOC:
   922     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   923       return "PREALLOC:CPU_NORMAL";
   924     }
   925     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   926       return "PREALLOC:CPU_LOW";
   927     }
   928   case PROCESS_PRIORITY_FOREGROUND_HIGH:
   929     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   930       return "FOREGROUND_HIGH:CPU_NORMAL";
   931     }
   932     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   933       return "FOREGROUND_HIGH:CPU_LOW";
   934     }
   935   case PROCESS_PRIORITY_FOREGROUND:
   936     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   937       return "FOREGROUND:CPU_NORMAL";
   938     }
   939     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   940       return "FOREGROUND:CPU_LOW";
   941     }
   942   case PROCESS_PRIORITY_FOREGROUND_KEYBOARD:
   943     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   944       return "FOREGROUND_KEYBOARD:CPU_NORMAL";
   945     }
   946     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   947       return "FOREGROUND_KEYBOARD:CPU_LOW";
   948     }
   949   case PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE:
   950     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   951       return "BACKGROUND_PERCEIVABLE:CPU_NORMAL";
   952     }
   953     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   954       return "BACKGROUND_PERCEIVABLE:CPU_LOW";
   955     }
   956   case PROCESS_PRIORITY_BACKGROUND_HOMESCREEN:
   957     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   958       return "BACKGROUND_HOMESCREEN:CPU_NORMAL";
   959     }
   960     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   961       return "BACKGROUND_HOMESCREEN:CPU_LOW";
   962     }
   963   case PROCESS_PRIORITY_BACKGROUND:
   964     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   965       return "BACKGROUND:CPU_NORMAL";
   966     }
   967     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   968       return "BACKGROUND:CPU_LOW";
   969     }
   970   case PROCESS_PRIORITY_UNKNOWN:
   971     if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
   972       return "UNKNOWN:CPU_NORMAL";
   973     }
   974     if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
   975       return "UNKNOWN:CPU_LOW";
   976     }
   977   default:
   978     // Fall through.  (|default| is here to silence warnings.)
   979     break;
   980   }
   982   MOZ_ASSERT(false);
   983   return "???";
   984 }
   986 static StaticAutoPtr<ObserverList<FMRadioOperationInformation> > sFMRadioObservers;
   988 static void
   989 InitializeFMRadioObserver()
   990 {
   991   if (!sFMRadioObservers) {
   992     sFMRadioObservers = new ObserverList<FMRadioOperationInformation>;
   993     ClearOnShutdown(&sFMRadioObservers);
   994   }
   995 }
   997 void
   998 RegisterFMRadioObserver(FMRadioObserver* aFMRadioObserver) {
   999   AssertMainThread();
  1000   InitializeFMRadioObserver();
  1001   sFMRadioObservers->AddObserver(aFMRadioObserver);
  1004 void
  1005 UnregisterFMRadioObserver(FMRadioObserver* aFMRadioObserver) {
  1006   AssertMainThread();
  1007   InitializeFMRadioObserver();
  1008   sFMRadioObservers->RemoveObserver(aFMRadioObserver);
  1011 void
  1012 NotifyFMRadioStatus(const FMRadioOperationInformation& aFMRadioState) {
  1013   InitializeFMRadioObserver();
  1014   sFMRadioObservers->Broadcast(aFMRadioState);
  1017 void
  1018 EnableFMRadio(const FMRadioSettings& aInfo) {
  1019   AssertMainThread();
  1020   PROXY_IF_SANDBOXED(EnableFMRadio(aInfo));
  1023 void
  1024 DisableFMRadio() {
  1025   AssertMainThread();
  1026   PROXY_IF_SANDBOXED(DisableFMRadio());
  1029 void
  1030 FMRadioSeek(const FMRadioSeekDirection& aDirection) {
  1031   AssertMainThread();
  1032   PROXY_IF_SANDBOXED(FMRadioSeek(aDirection));
  1035 void
  1036 GetFMRadioSettings(FMRadioSettings* aInfo) {
  1037   AssertMainThread();
  1038   PROXY_IF_SANDBOXED(GetFMRadioSettings(aInfo));
  1041 void
  1042 SetFMRadioFrequency(const uint32_t aFrequency) {
  1043   AssertMainThread();
  1044   PROXY_IF_SANDBOXED(SetFMRadioFrequency(aFrequency));
  1047 uint32_t
  1048 GetFMRadioFrequency() {
  1049   AssertMainThread();
  1050   RETURN_PROXY_IF_SANDBOXED(GetFMRadioFrequency(), 0);
  1053 bool
  1054 IsFMRadioOn() {
  1055   AssertMainThread();
  1056   RETURN_PROXY_IF_SANDBOXED(IsFMRadioOn(), false);
  1059 uint32_t
  1060 GetFMRadioSignalStrength() {
  1061   AssertMainThread();
  1062   RETURN_PROXY_IF_SANDBOXED(GetFMRadioSignalStrength(), 0);
  1065 void
  1066 CancelFMRadioSeek() {
  1067   AssertMainThread();
  1068   PROXY_IF_SANDBOXED(CancelFMRadioSeek());
  1071 FMRadioSettings
  1072 GetFMBandSettings(FMRadioCountry aCountry) {
  1073   FMRadioSettings settings;
  1075   switch (aCountry) {
  1076     case FM_RADIO_COUNTRY_US:
  1077     case FM_RADIO_COUNTRY_EU:
  1078       settings.upperLimit() = 108000;
  1079       settings.lowerLimit() = 87800;
  1080       settings.spaceType() = 200;
  1081       settings.preEmphasis() = 75;
  1082       break;
  1083     case FM_RADIO_COUNTRY_JP_STANDARD:
  1084       settings.upperLimit() = 76000;
  1085       settings.lowerLimit() = 90000;
  1086       settings.spaceType() = 100;
  1087       settings.preEmphasis() = 50;
  1088       break;
  1089     case FM_RADIO_COUNTRY_CY:
  1090     case FM_RADIO_COUNTRY_DE:
  1091     case FM_RADIO_COUNTRY_DK:
  1092     case FM_RADIO_COUNTRY_ES:
  1093     case FM_RADIO_COUNTRY_FI:
  1094     case FM_RADIO_COUNTRY_FR:
  1095     case FM_RADIO_COUNTRY_HU:
  1096     case FM_RADIO_COUNTRY_IR:
  1097     case FM_RADIO_COUNTRY_IT:
  1098     case FM_RADIO_COUNTRY_KW:
  1099     case FM_RADIO_COUNTRY_LT:
  1100     case FM_RADIO_COUNTRY_ML:
  1101     case FM_RADIO_COUNTRY_NO:
  1102     case FM_RADIO_COUNTRY_OM:
  1103     case FM_RADIO_COUNTRY_PG:
  1104     case FM_RADIO_COUNTRY_NL:
  1105     case FM_RADIO_COUNTRY_CZ:
  1106     case FM_RADIO_COUNTRY_UK:
  1107     case FM_RADIO_COUNTRY_RW:
  1108     case FM_RADIO_COUNTRY_SN:
  1109     case FM_RADIO_COUNTRY_SI:
  1110     case FM_RADIO_COUNTRY_ZA:
  1111     case FM_RADIO_COUNTRY_SE:
  1112     case FM_RADIO_COUNTRY_CH:
  1113     case FM_RADIO_COUNTRY_TW:
  1114     case FM_RADIO_COUNTRY_UA:
  1115       settings.upperLimit() = 108000;
  1116       settings.lowerLimit() = 87500;
  1117       settings.spaceType() = 100;
  1118       settings.preEmphasis() = 50;
  1119       break;
  1120     case FM_RADIO_COUNTRY_VA:
  1121     case FM_RADIO_COUNTRY_MA:
  1122     case FM_RADIO_COUNTRY_TR:
  1123       settings.upperLimit() = 10800;
  1124       settings.lowerLimit() = 87500;
  1125       settings.spaceType() = 100;
  1126       settings.preEmphasis() = 75;
  1127       break;
  1128     case FM_RADIO_COUNTRY_AU:
  1129     case FM_RADIO_COUNTRY_BD:
  1130       settings.upperLimit() = 108000;
  1131       settings.lowerLimit() = 87500;
  1132       settings.spaceType() = 200;
  1133       settings.preEmphasis() = 75;
  1134       break;
  1135     case FM_RADIO_COUNTRY_AW:
  1136     case FM_RADIO_COUNTRY_BS:
  1137     case FM_RADIO_COUNTRY_CO:
  1138     case FM_RADIO_COUNTRY_KR:
  1139       settings.upperLimit() = 108000;
  1140       settings.lowerLimit() = 88000;
  1141       settings.spaceType() = 200;
  1142       settings.preEmphasis() = 75;
  1143       break;
  1144     case FM_RADIO_COUNTRY_EC:
  1145       settings.upperLimit() = 108000;
  1146       settings.lowerLimit() = 88000;
  1147       settings.spaceType() = 200;
  1148       settings.preEmphasis() = 0;
  1149       break;
  1150     case FM_RADIO_COUNTRY_GM:
  1151       settings.upperLimit() = 108000;
  1152       settings.lowerLimit() = 88000;
  1153       settings.spaceType() = 0;
  1154       settings.preEmphasis() = 75;
  1155       break;
  1156     case FM_RADIO_COUNTRY_QA:
  1157       settings.upperLimit() = 108000;
  1158       settings.lowerLimit() = 88000;
  1159       settings.spaceType() = 200;
  1160       settings.preEmphasis() = 50;
  1161       break;
  1162     case FM_RADIO_COUNTRY_SG:
  1163       settings.upperLimit() = 108000;
  1164       settings.lowerLimit() = 88000;
  1165       settings.spaceType() = 200;
  1166       settings.preEmphasis() = 50;
  1167       break;
  1168     case FM_RADIO_COUNTRY_IN:
  1169       settings.upperLimit() = 100000;
  1170       settings.lowerLimit() = 108000;
  1171       settings.spaceType() = 100;
  1172       settings.preEmphasis() = 50;
  1173       break;
  1174     case FM_RADIO_COUNTRY_NZ:
  1175       settings.upperLimit() = 100000;
  1176       settings.lowerLimit() = 88000;
  1177       settings.spaceType() = 50;
  1178       settings.preEmphasis() = 50;
  1179       break;
  1180     case FM_RADIO_COUNTRY_USER_DEFINED:
  1181       break;
  1182     default:
  1183       MOZ_ASSERT(0);
  1184       break;
  1185     };
  1186     return settings;
  1189 void FactoryReset()
  1191   AssertMainThread();
  1192   PROXY_IF_SANDBOXED(FactoryReset());
  1195 void
  1196 StartDiskSpaceWatcher()
  1198   AssertMainProcess();
  1199   AssertMainThread();
  1200   PROXY_IF_SANDBOXED(StartDiskSpaceWatcher());
  1203 void
  1204 StopDiskSpaceWatcher()
  1206   AssertMainProcess();
  1207   AssertMainThread();
  1208   PROXY_IF_SANDBOXED(StopDiskSpaceWatcher());
  1211 uint32_t
  1212 GetTotalSystemMemory()
  1214   return hal_impl::GetTotalSystemMemory();
  1218 } // namespace hal
  1219 } // namespace mozilla

mercurial