author | Steven Lee <slee@mozilla.com> |
Sun, 22 Apr 2012 14:09:22 -0400 | |
changeset 95842 | e2af0b79da44efb6b6256109944974889e83d3f0 |
parent 95841 | 6c8fe1624a6bd82758e6e38344ddedd35bd9d376 |
child 95843 | ce9fff905894b2d253c4d9cb496e286f6f801d6a |
push id | 160 |
push user | lsblakk@mozilla.com |
push date | Fri, 13 Jul 2012 18:18:57 +0000 |
treeherder | mozilla-release@228ba1a111fc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cjones, b2g-only |
bugs | 736939 |
milestone | 14.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
|
hal/Hal.cpp | file | annotate | diff | comparison | revisions | |
hal/Hal.h | file | annotate | diff | comparison | revisions | |
hal/HalInternal.h | file | annotate | diff | comparison | revisions | |
hal/HalTypes.h | file | annotate | diff | comparison | revisions | |
hal/Makefile.in | file | annotate | diff | comparison | revisions | |
hal/fallback/FallbackSwitch.cpp | file | annotate | diff | comparison | revisions | |
hal/gonk/GonkSwitch.cpp | file | annotate | diff | comparison | revisions | |
hal/sandbox/PHal.ipdl | file | annotate | diff | comparison | revisions | |
hal/sandbox/SandboxHal.cpp | file | annotate | diff | comparison | revisions |
--- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -591,10 +591,88 @@ LockScreenOrientation(const dom::ScreenO void UnlockScreenOrientation() { AssertMainThread(); PROXY_IF_SANDBOXED(UnlockScreenOrientation()); } +void +EnableSwitchNotifications(hal::SwitchDevice aDevice) { + AssertMainThread(); + PROXY_IF_SANDBOXED(EnableSwitchNotifications(aDevice)); +} + +void +DisableSwitchNotifications(hal::SwitchDevice aDevice) { + AssertMainThread(); + PROXY_IF_SANDBOXED(DisableSwitchNotifications(aDevice)); +} + +hal::SwitchState GetCurrentSwitchState(hal::SwitchDevice aDevice) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(GetCurrentSwitchState(aDevice)); +} + +typedef mozilla::ObserverList<SwitchEvent> SwitchObserverList; + +static SwitchObserverList *sSwitchObserverLists = NULL; + +static SwitchObserverList& +GetSwitchObserverList(hal::SwitchDevice aDevice) { + MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); + if (sSwitchObserverLists == NULL) { + sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE]; + } + return sSwitchObserverLists[aDevice]; +} + +static void +ReleaseObserversIfNeeded() { + for (int i = 0; i < NUM_SWITCH_DEVICE; i++) { + if (sSwitchObserverLists[i].Length() != 0) + return; + } + + //The length of every list is 0, no observer in the list. + delete [] sSwitchObserverLists; + sSwitchObserverLists = NULL; +} + +void +RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver) +{ + AssertMainThread(); + SwitchObserverList& observer = GetSwitchObserverList(aDevice); + observer.AddObserver(aObserver); + if (observer.Length() == 1) { + EnableSwitchNotifications(aDevice); + } +} + +void +UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aObserver) +{ + AssertMainThread(); + SwitchObserverList& observer = GetSwitchObserverList(aDevice); + observer.RemoveObserver(aObserver); + if (observer.Length() == 0) { + DisableSwitchNotifications(aDevice); + ReleaseObserversIfNeeded(); + } +} + +void +NotifySwitchChange(const hal::SwitchEvent& aEvent) +{ + // When callback this notification, main thread may call unregister function + // first. We should check if this pointer is valid. + if (!sSwitchObserverLists) + return; + + SwitchObserverList& observer = GetSwitchObserverList(aEvent.device()); + observer.Broadcast(aEvent); +} + } // namespace hal } // namespace mozilla
--- a/hal/Hal.h +++ b/hal/Hal.h @@ -340,16 +340,41 @@ void NotifyScreenOrientationChange(const */ bool LockScreenOrientation(const dom::ScreenOrientation& aOrientation); /** * Unlock the screen orientation. */ void UnlockScreenOrientation(); +/** + * Register an observer for the switch of given SwitchDevice. + * + * The observer will receive data whenever the data generated by the + * given switch. + */ +void RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwitchObserver); + +/** + * Unregister an observer for the switch of given SwitchDevice. + */ +void UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwitchObserver); + +/** + * Notify the state of the switch. + * + * This API is internal to hal; clients shouldn't call it directly. + */ +void NotifySwitchChange(const hal::SwitchEvent& aEvent); + +/** + * Get current switch information. + */ +hal::SwitchState GetCurrentSwitchState(hal::SwitchDevice aDevice); + } // namespace MOZ_HAL_NAMESPACE } // namespace mozilla #ifdef MOZ_DEFINED_HAL_NAMESPACE # undef MOZ_DEFINED_HAL_NAMESPACE # undef MOZ_HAL_NAMESPACE #endif
--- a/hal/HalInternal.h +++ b/hal/HalInternal.h @@ -82,12 +82,22 @@ void DisableNetworkNotifications(); */ void EnableScreenOrientationNotifications(); /** * Disables screen orientation notifications from the backend. */ void DisableScreenOrientationNotifications(); +/** + * Enable switch notifications from the backend + */ +void EnableSwitchNotifications(hal::SwitchDevice aDevice); + +/** + * Disable switch notifications from the backend + */ +void DisableSwitchNotifications(hal::SwitchDevice aDevice); + } // namespace MOZ_HAL_NAMESPACE } // namespace mozilla #endif // mozilla_HalInternal_h
--- a/hal/HalTypes.h +++ b/hal/HalTypes.h @@ -32,16 +32,32 @@ enum LightMode { eHalLightMode_Sensor = 1 // brightness is managed by a light sensor }; enum FlashMode { eHalLightFlash_None = 0, eHalLightFlash_Timed = 1, // timed flashing. Use flashOnMS and flashOffMS for timing eHalLightFlash_Hardware = 2 // hardware assisted flashing }; +class SwitchEvent; + +enum SwitchDevice { + SWITCH_DEVICE_UNKNOWN = -1, + SWITCH_HEADPHONES, + NUM_SWITCH_DEVICE +}; + +enum SwitchState { + SWITCH_STATE_UNKNOWN = -1, + SWITCH_STATE_ON, + SWITCH_STATE_OFF, + NUM_SWITCH_STATE +}; + +typedef Observer<SwitchEvent> SwitchObserver; } // namespace hal } // namespace mozilla namespace mozilla { namespace hal { /** * Used by ModifyWakeLock @@ -92,11 +108,32 @@ struct ParamTraits<mozilla::hal::FlashMo */ template <> struct ParamTraits<mozilla::hal::WakeLockControl> : public EnumSerializer<mozilla::hal::WakeLockControl, mozilla::hal::WAKE_LOCK_REMOVE_ONE, mozilla::hal::WAKE_LOCK_ADD_ONE> {}; +/** + * Serializer for SwitchState + */ +template <> +struct ParamTraits<mozilla::hal::SwitchState>: + public EnumSerializer<mozilla::hal::SwitchState, + mozilla::hal::SWITCH_STATE_UNKNOWN, + mozilla::hal::NUM_SWITCH_STATE> { +}; + +/** + * Serializer for SwitchDevice + */ +template <> +struct ParamTraits<mozilla::hal::SwitchDevice>: + public EnumSerializer<mozilla::hal::SwitchDevice, + mozilla::hal::SWITCH_DEVICE_UNKNOWN, + mozilla::hal::NUM_SWITCH_DEVICE> { +}; + + } // namespace IPC #endif // mozilla_hal_Types_h
--- a/hal/Makefile.in +++ b/hal/Makefile.in @@ -80,16 +80,17 @@ CPPSRCS += \ AndroidSensor.cpp \ $(NULL) else ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += \ GonkHal.cpp \ Power.cpp \ GonkSensor.cpp \ UeventPoller.cpp \ + GonkSwitch.cpp \ $(NULL) else ifeq (Linux,$(OS_TARGET)) CPPSRCS += \ LinuxHal.cpp \ FallbackSensor.cpp \ Power.cpp \ $(NULL) ifdef MOZ_ENABLE_DBUS @@ -116,16 +117,17 @@ CPPSRCS += \ $(NULL) endif ifneq (gonk,$(MOZ_WIDGET_TOOLKIT)) #{ CPPSRCS += \ FallbackLights.cpp \ FallbackTime.cpp \ FallbackWakeLocks.cpp \ + FallbackSwitch.cpp \ $(NULL) endif #} # Screen Orientation backend ifneq (android,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += ScreenOrientationFallback.cpp endif
new file mode 100644 --- /dev/null +++ b/hal/fallback/FallbackSwitch.cpp @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "mozilla/Hal.h" + +using namespace mozilla::hal; + +namespace mozilla { +namespace hal_impl { + +void +EnableSwitchNotifications(SwitchDevice aDevice) +{ +} + +void +DisableSwitchNotifications(SwitchDevice aDevice) +{ +} + +SwitchState +GetCurrentSwitchState(SwitchDevice aDevice) { + return SWITCH_STATE_UNKNOWN; +} + +} // namespace hal_impl +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/hal/gonk/GonkSwitch.cpp @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 <android/log.h> +#include <sysutils/NetlinkEvent.h> + +#include "base/message_loop.h" + +#include "Hal.h" +#include "nsXULAppAPI.h" +#include "UeventPoller.h" + +using namespace mozilla::hal; + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GonkSwitch" , ## args) + +namespace mozilla { +namespace hal_impl { + +struct {const char* name; SwitchDevice device; } kSwitchNameMap[] = { + { "h2w", SWITCH_HEADPHONES }, + { NULL, SWITCH_DEVICE_UNKNOWN }, +}; + +static SwitchDevice +NameToDevice(const char* name) { + for (int i = 0; kSwitchNameMap[i].device != SWITCH_DEVICE_UNKNOWN; i++) { + if (strcmp(name, kSwitchNameMap[i].name) == 0) { + return kSwitchNameMap[i].device; + } + } + return SWITCH_DEVICE_UNKNOWN; +} + +class SwitchEventRunnable : public nsRunnable +{ +public: + SwitchEventRunnable(SwitchEvent& event) : mEvent(event) {} + + NS_IMETHOD Run() { + NotifySwitchChange(mEvent); + return NS_OK; + } +private: + SwitchEvent mEvent; +}; + +class SwitchEventObserver : public IUeventObserver +{ +public: + SwitchEventObserver() : mEnableNum(0) { + InternalInit(); + } + ~SwitchEventObserver() {} + + int GetEnableCount() { + return mEnableNum; + } + + void EnableSwitch(SwitchDevice aDevice) { + mEventInfo[aDevice].mEnable = true; + mEnableNum++; + } + + void DisableSwitch(SwitchDevice aDevice) { + mEventInfo[aDevice].mEnable = false; + mEnableNum--; + } + + void Notify(const NetlinkEvent& event) { + const char* name; + const char* state; + + SwitchDevice device = ProcessEvent(event, &name, &state); + if (device == SWITCH_DEVICE_UNKNOWN) { + return; + } + + EventInfo& info = mEventInfo[device]; + info.mEvent.status() = atoi(state) == 0 ? SWITCH_STATE_OFF : SWITCH_STATE_ON; + if (info.mEnable) { + NS_DispatchToMainThread(new SwitchEventRunnable(info.mEvent)); + } + } + + SwitchState GetCurrentInformation(SwitchDevice aDevice) { + return mEventInfo[aDevice].mEvent.status(); + } + +private: + class EventInfo { + public: + EventInfo() : mEnable(false) {} + SwitchEvent mEvent; + bool mEnable; + }; + + EventInfo mEventInfo[NUM_SWITCH_DEVICE]; + size_t mEnableNum; + + void InternalInit() { + for (int i = 0; i < NUM_SWITCH_DEVICE; i++) { + mEventInfo[i].mEvent.device() = kSwitchNameMap[i].device; + mEventInfo[i].mEvent.status() = SWITCH_STATE_UNKNOWN; + } + } + + bool GetEventInfo(const NetlinkEvent& event, const char** name, const char** state) { + //working around the android code not being const-correct + NetlinkEvent *e = const_cast<NetlinkEvent*>(&event); + const char* subsystem = e->getSubsystem(); + + if (!subsystem || strcmp(subsystem, "switch")) { + return false; + } + + *name = e->findParam("SWITCH_NAME"); + *state = e->findParam("SWITCH_STATE"); + + if (!*name || !*state) { + return false; + } + return true; + } + + SwitchDevice ProcessEvent(const NetlinkEvent& event, const char** name, const char** state) { + bool rv = GetEventInfo(event, name, state); + NS_ENSURE_TRUE(rv, SWITCH_DEVICE_UNKNOWN); + return NameToDevice(*name); + } +}; + +SwitchEventObserver* sSwitchObserver; + +static void +InitializeResourceIfNeed() +{ + if (!sSwitchObserver) { + sSwitchObserver = new SwitchEventObserver(); + RegisterUeventListener(sSwitchObserver); + } +} + +static void +ReleaseResourceIfNeed() +{ + if (sSwitchObserver->GetEnableCount() == 0) { + UnregisterUeventListener(sSwitchObserver); + delete sSwitchObserver; + sSwitchObserver = NULL; + } +} + +static void +EnableSwitchNotificationsIOThread(SwitchDevice aDevice) +{ + InitializeResourceIfNeed(); + sSwitchObserver->EnableSwitch(aDevice); +} + +void +EnableSwitchNotifications(SwitchDevice aDevice) +{ + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(EnableSwitchNotificationsIOThread, aDevice)); +} + +static void +DisableSwitchNotificationsIOThread(SwitchDevice aDevice) +{ + MOZ_ASSERT(sSwitchObserver->GetEnableCount()); + sSwitchObserver->DisableSwitch(aDevice); + ReleaseResourceIfNeed(); +} + +void +DisableSwitchNotifications(SwitchDevice aDevice) +{ + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(DisableSwitchNotificationsIOThread, aDevice)); +} + +SwitchState +GetCurrentSwitchState(SwitchDevice aDevice) +{ + MOZ_ASSERT(sSwitchObserver && sSwitchObserver->GetEnableCount()); + return sSwitchObserver->GetCurrentInformation(aDevice); +} + +} // hal_impl +} //mozilla
--- a/hal/sandbox/PHal.ipdl +++ b/hal/sandbox/PHal.ipdl @@ -47,16 +47,18 @@ include "mozilla/dom/ScreenOrientation.h using PRTime; using mozilla::hal::FlashMode; using mozilla::hal::LightType; using mozilla::hal::LightMode; using mozilla::hal::SensorType; using mozilla::hal::SensorAccuracyType; using mozilla::hal::WakeLockControl; using mozilla::dom::ScreenOrientation; +using mozilla::hal::SwitchState; +using mozilla::hal::SwitchDevice; namespace mozilla { namespace hal { struct BatteryInformation { double level; bool charging; double remainingTime; @@ -77,16 +79,21 @@ namespace hal { float[] values; SensorAccuracyType accuracy; }; struct NetworkInformation { double bandwidth; bool canBeMetered; }; + + struct SwitchEvent { + SwitchDevice device; + SwitchState status; + }; } namespace hal { struct WakeLockInformation { uint32_t numLocks; uint32_t numHidden; nsString topic; }; @@ -97,16 +104,17 @@ namespace hal_sandbox { sync protocol PHal { manager PContent; child: NotifyBatteryChange(BatteryInformation aBatteryInfo); NotifyNetworkChange(NetworkInformation aNetworkInfo); NotifyWakeLockChange(WakeLockInformation aWakeLockInfo); NotifyScreenOrientationChange(ScreenOrientation aScreenOrientation); + NotifySwitchChange(SwitchEvent aEvent); parent: Vibrate(uint32[] pattern, uint64[] id, PBrowser browser); CancelVibrate(uint64[] id, PBrowser browser); EnableBatteryNotifications(); DisableBatteryNotifications(); sync GetCurrentBatteryInformation() @@ -145,16 +153,21 @@ parent: EnableScreenOrientationNotifications(); DisableScreenOrientationNotifications(); sync GetCurrentScreenOrientation() returns (ScreenOrientation aScreenOrientation); sync LockScreenOrientation(ScreenOrientation aOrientation) returns (bool allowed); UnlockScreenOrientation(); + + EnableSwitchNotifications(SwitchDevice aDevice); + DisableSwitchNotifications(SwitchDevice aDevice); + sync GetCurrentSwitchState(SwitchDevice aDevice) + returns (SwitchState aState); child: NotifySensorChange(SensorData aSensorData); parent: EnableSensorNotifications(SensorType aSensor); DisableSensorNotifications(SensorType aSensor);
--- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -235,22 +235,43 @@ ModifyWakeLock(const nsAString &aTopic, } void GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo) { Hal()->SendGetWakeLockInfo(nsString(aTopic), aWakeLockInfo); } +void +EnableSwitchNotifications(SwitchDevice aDevice) +{ + Hal()->SendEnableSwitchNotifications(aDevice); +} + +void +DisableSwitchNotifications(SwitchDevice aDevice) +{ + Hal()->SendDisableSwitchNotifications(aDevice); +} + +SwitchState +GetCurrentSwitchState(SwitchDevice aDevice) +{ + SwitchState state; + Hal()->SendGetCurrentSwitchState(aDevice, &state); + return state; +} + class HalParent : public PHalParent , public BatteryObserver , public NetworkObserver , public ISensorObserver , public WakeLockObserver , public ScreenOrientationObserver + , public SwitchObserver { public: NS_OVERRIDE virtual bool RecvVibrate(const InfallibleTArray<unsigned int>& pattern, const InfallibleTArray<uint64> &id, PBrowserParent *browserParent) { // Check whether browserParent is active. We should have already @@ -496,16 +517,42 @@ public: hal::GetWakeLockInfo(aTopic, aWakeLockInfo); return true; } void Notify(const WakeLockInformation& aWakeLockInfo) { unused << SendNotifyWakeLockChange(aWakeLockInfo); } + + NS_OVERRIDE virtual bool + RecvEnableSwitchNotifications(const SwitchDevice& aDevice) + { + hal::RegisterSwitchObserver(aDevice, this); + return true; + } + + NS_OVERRIDE virtual bool + RecvDisableSwitchNotifications(const SwitchDevice& aDevice) + { + hal::UnregisterSwitchObserver(aDevice, this); + return true; + } + + void Notify(const SwitchEvent& aSwitchEvent) + { + unused << SendNotifySwitchChange(aSwitchEvent); + } + + NS_OVERRIDE virtual bool + RecvGetCurrentSwitchState(const SwitchDevice& aDevice, hal::SwitchState *aState) + { + *aState = hal::GetCurrentSwitchState(aDevice); + return true; + } }; class HalChild : public PHalChild { public: NS_OVERRIDE virtual bool RecvNotifyBatteryChange(const BatteryInformation& aBatteryInfo) { hal::NotifyBatteryChange(aBatteryInfo); return true; @@ -526,16 +573,22 @@ public: return true; } NS_OVERRIDE virtual bool RecvNotifyScreenOrientationChange(const ScreenOrientation& aScreenOrientation) { hal::NotifyScreenOrientationChange(aScreenOrientation); return true; } + + NS_OVERRIDE virtual bool + RecvNotifySwitchChange(const mozilla::hal::SwitchEvent& aEvent) { + hal::NotifySwitchChange(aEvent); + return true; + } }; bool HalChild::RecvNotifySensorChange(const hal::SensorData &aSensorData) { hal::NotifySensorChange(aSensorData); return true; }