Bug 625664 - accelerometer support using Windows 7 Sensor API. r=dougt
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Tue, 01 May 2012 12:04:30 +0900
changeset 96914 61c2bc0d9a41df0c78f08b567e4dfdc9383a769d
parent 96913 ffe230d1ee936d003e7201651eb278146e7a4771
child 96915 221db28204cfd7258126b0e6fadeb6c6ac8d6fbc
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt
bugs625664
milestone15.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 625664 - accelerometer support using Windows 7 Sensor API. r=dougt
hal/Makefile.in
hal/windows/WindowsSensor.cpp
toolkit/library/Makefile.in
--- a/hal/Makefile.in
+++ b/hal/Makefile.in
@@ -95,17 +95,17 @@ CPPSRCS += \
   $(NULL)
 ifdef MOZ_ENABLE_DBUS
 CPPSRCS += UPowerClient.cpp
 endif
 else ifeq (WINNT,$(OS_TARGET))
 CPPSRCS += \
   WindowsHal.cpp \
   WindowsBattery.cpp \
-  FallbackSensor.cpp \
+  WindowsSensor.cpp \
   $(NULL)
 else ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += \
   FallbackHal.cpp \
   $(NULL)
 CMMSRCS += \
   CocoaSensor.mm \
   smslib.mm \
new file mode 100644
--- /dev/null
+++ b/hal/windows/WindowsSensor.cpp
@@ -0,0 +1,182 @@
+/* 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 "Hal.h"
+
+#include <sensorsapi.h>
+#include <sensors.h>
+#include <portabledevicetypes.h>
+
+#define MEAN_GRAVITY 9.80665
+#define DEFAULT_SENSOR_POLL 100
+
+using namespace mozilla::hal;
+
+namespace mozilla {
+namespace hal_impl {
+
+static nsRefPtr<ISensor> sAccelerometer;
+
+class SensorEvent : public ISensorEvents {
+public:
+  SensorEvent() : mCount(0) {
+  }
+
+  // IUnknown interface
+
+  STDMETHODIMP_(ULONG) AddRef() {
+    return InterlockedIncrement(&mCount);
+  }
+
+  STDMETHODIMP_(ULONG) Release() {
+    ULONG count = InterlockedDecrement(&mCount);
+    if (!count) {
+      delete this;
+      return 0;
+    }
+    return count;
+  }
+
+  STDMETHODIMP QueryInterface(REFIID iid, void** ppv) {
+    if (iid == IID_IUnknown) {
+      *ppv = static_cast<IUnknown*>(this);
+    } else if (iid == IID_ISensorEvents) {
+      *ppv = static_cast<ISensorEvents*>(this);
+    } else {
+      return E_NOINTERFACE;
+    }
+    AddRef();
+    return S_OK;
+  }
+
+  // ISensorEvents interface
+
+  STDMETHODIMP OnEvent(ISensor *aSensor, REFGUID aId, IPortableDeviceValues *aData) {
+    return S_OK;
+  }
+
+  STDMETHODIMP OnLeave(REFSENSOR_ID aId) {
+    return S_OK;
+  }
+
+  STDMETHODIMP OnStateChanged(ISensor *aSensor, SensorState state) {
+    return S_OK;
+  }
+
+  STDMETHODIMP OnDataUpdated(ISensor *aSensor, ISensorDataReport *aReport) {
+    PROPVARIANT v;
+    HRESULT hr;
+    InfallibleTArray<float> values;
+
+    // X-axis acceleration in g's
+    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v);
+    if (FAILED(hr)) {
+      return hr;
+    }
+    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+    // Y-axis acceleration in g's
+    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v);
+    if (FAILED(hr)) {
+      return hr;
+    }
+    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+    // Z-axis acceleration in g's
+    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v);
+    if (FAILED(hr)) {
+      return hr;
+    }
+    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+    hal::SensorData sdata(hal::SENSOR_ACCELERATION,
+                          PR_Now(),
+                          values,
+                          hal::SENSOR_ACCURACY_UNKNOWN);
+    hal::NotifySensorChange(sdata);
+
+    return S_OK;
+  }
+
+private:
+  ULONG mCount;
+};
+
+void
+EnableSensorNotifications(SensorType aSensor)
+{
+  if (aSensor != SENSOR_ACCELERATION) {
+    return;
+  }
+
+  if (sAccelerometer) {
+    return;
+  }
+
+  nsRefPtr<ISensorManager> manager;
+  if (FAILED(CoCreateInstance(CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER,
+                              IID_ISensorManager, getter_AddRefs(manager)))) {
+    return;
+  }
+
+  // accelerometer event
+
+  nsRefPtr<ISensorCollection> collection;
+  if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D,
+                                       getter_AddRefs(collection)))) {
+    return;
+  }
+
+  ULONG count = 0;
+  collection->GetCount(&count);
+  if (!count) {
+    return;
+  }
+
+  nsRefPtr<ISensor> sensor;
+  collection->GetAt(0, getter_AddRefs(sensor));
+  if (!sensor) {
+    return;
+  }
+
+  // Set report interval to 100ms if possible. 
+  // Default value depends on drivers.
+  nsRefPtr<IPortableDeviceValues> values;
+  if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, NULL,
+                                 CLSCTX_INPROC_SERVER,
+                                 IID_IPortableDeviceValues,
+                                 getter_AddRefs(values)))) {
+    if (SUCCEEDED(values->SetUnsignedIntegerValue(
+                    SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
+                    DEFAULT_SENSOR_POLL))) {
+      nsRefPtr<IPortableDeviceValues> returns;
+      sensor->SetProperties(values, getter_AddRefs(returns));
+    }
+  }
+
+  nsRefPtr<SensorEvent> event = new SensorEvent();
+  nsRefPtr<ISensorEvents> sensorEvents;
+  if (FAILED(event->QueryInterface(IID_ISensorEvents,
+                                   getter_AddRefs(sensorEvents)))) {
+    return;
+  }
+
+  if (FAILED(sensor->SetEventSink(sensorEvents))) {
+    return;
+  }
+
+  sAccelerometer = sensor;
+}
+
+void
+DisableSensorNotifications(SensorType aSensor)
+{
+  if (aSensor == SENSOR_ACCELERATION && sAccelerometer) {
+    sAccelerometer->SetEventSink(NULL);
+    sAccelerometer = nsnull;
+  }
+}
+
+} // hal_impl
+} // mozilla
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -517,17 +517,17 @@ ifeq ($(OS_ARCH),SunOS)
 ifdef GNU_CC
 EXTRA_DSO_LDOPTS += -lelf
 else
 EXTRA_DSO_LDOPTS += -lelf -ldemangle
 endif
 endif
 
 ifeq ($(OS_ARCH),WINNT)
-OS_LIBS += $(call EXPAND_LIBNAME,shell32 ole32 version winspool comdlg32 imm32 msimg32 shlwapi psapi ws2_32 dbghelp rasapi32 rasdlg iphlpapi uxtheme setupapi secur32)
+OS_LIBS += $(call EXPAND_LIBNAME,shell32 ole32 version winspool comdlg32 imm32 msimg32 shlwapi psapi ws2_32 dbghelp rasapi32 rasdlg iphlpapi uxtheme setupapi secur32 sensorsapi portabledeviceguids)
 ifdef MOZ_CRASHREPORTER
 OS_LIBS += $(call EXPAND_LIBNAME,wininet)
 endif
 ifdef ACCESSIBILITY
 OS_LIBS += $(call EXPAND_LIBNAME,oleacc)
 endif
 ifdef _MSC_VER
 OS_LIBS += $(call EXPAND_LIBNAME,delayimp)