tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WindowsSensor.cpp (4312B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "Hal.h"
      6 
      7 #include <sensorsapi.h>
      8 #include <sensors.h>
      9 #include <portabledevicetypes.h>
     10 
     11 #define MEAN_GRAVITY 9.80665
     12 #define DEFAULT_SENSOR_POLL 100
     13 
     14 using namespace mozilla::hal;
     15 
     16 namespace mozilla {
     17 namespace hal_impl {
     18 
     19 constinit static RefPtr<ISensor> sAccelerometer;
     20 
     21 class SensorEvent final : public ISensorEvents {
     22 public:
     23  SensorEvent() : mCount(0) {}
     24 
     25  // IUnknown interface
     26 
     27  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&mCount); }
     28 
     29  STDMETHODIMP_(ULONG) Release() {
     30    ULONG count = InterlockedDecrement(&mCount);
     31    if (!count) {
     32      delete this;
     33      return 0;
     34    }
     35    return count;
     36  }
     37 
     38  STDMETHODIMP QueryInterface(REFIID iid, void** ppv) {
     39    if (iid == IID_IUnknown) {
     40      *ppv = static_cast<IUnknown*>(this);
     41    } else if (iid == IID_ISensorEvents) {
     42      *ppv = static_cast<ISensorEvents*>(this);
     43    } else {
     44      return E_NOINTERFACE;
     45    }
     46    AddRef();
     47    return S_OK;
     48  }
     49 
     50  // ISensorEvents interface
     51 
     52  STDMETHODIMP OnEvent(ISensor* aSensor, REFGUID aId,
     53                       IPortableDeviceValues* aData) {
     54    return S_OK;
     55  }
     56 
     57  STDMETHODIMP OnLeave(REFSENSOR_ID aId) { return S_OK; }
     58 
     59  STDMETHODIMP OnStateChanged(ISensor* aSensor, SensorState state) {
     60    return S_OK;
     61  }
     62 
     63  STDMETHODIMP OnDataUpdated(ISensor* aSensor, ISensorDataReport* aReport) {
     64    PROPVARIANT v;
     65    HRESULT hr;
     66    nsTArray<float> values;
     67 
     68    // X-axis acceleration in g's
     69    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v);
     70    if (FAILED(hr)) {
     71      return hr;
     72    }
     73    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
     74 
     75    // Y-axis acceleration in g's
     76    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v);
     77    if (FAILED(hr)) {
     78      return hr;
     79    }
     80    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
     81 
     82    // Z-axis acceleration in g's
     83    hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v);
     84    if (FAILED(hr)) {
     85      return hr;
     86    }
     87    values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
     88 
     89    hal::SensorData sdata(hal::SENSOR_ACCELERATION, PR_Now(), values);
     90    hal::NotifySensorChange(sdata);
     91 
     92    return S_OK;
     93  }
     94 
     95 private:
     96  ULONG mCount;
     97 };
     98 
     99 void EnableSensorNotifications(SensorType aSensor) {
    100  if (aSensor != SENSOR_ACCELERATION) {
    101    return;
    102  }
    103 
    104  if (sAccelerometer) {
    105    return;
    106  }
    107 
    108  RefPtr<ISensorManager> manager;
    109  if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr,
    110                              CLSCTX_INPROC_SERVER, IID_ISensorManager,
    111                              getter_AddRefs(manager)))) {
    112    return;
    113  }
    114 
    115  // accelerometer event
    116 
    117  RefPtr<ISensorCollection> collection;
    118  if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D,
    119                                       getter_AddRefs(collection)))) {
    120    return;
    121  }
    122 
    123  ULONG count = 0;
    124  collection->GetCount(&count);
    125  if (!count) {
    126    return;
    127  }
    128 
    129  RefPtr<ISensor> sensor;
    130  collection->GetAt(0, getter_AddRefs(sensor));
    131  if (!sensor) {
    132    return;
    133  }
    134 
    135  // Set report interval to 100ms if possible.
    136  // Default value depends on drivers.
    137  RefPtr<IPortableDeviceValues> values;
    138  if (SUCCEEDED(CoCreateInstance(
    139          CLSID_PortableDeviceValues, nullptr, CLSCTX_INPROC_SERVER,
    140          IID_IPortableDeviceValues, getter_AddRefs(values)))) {
    141    if (SUCCEEDED(values->SetUnsignedIntegerValue(
    142            SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, DEFAULT_SENSOR_POLL))) {
    143      RefPtr<IPortableDeviceValues> returns;
    144      sensor->SetProperties(values, getter_AddRefs(returns));
    145    }
    146  }
    147 
    148  RefPtr<SensorEvent> event = new SensorEvent();
    149  RefPtr<ISensorEvents> sensorEvents;
    150  if (FAILED(event->QueryInterface(IID_ISensorEvents,
    151                                   getter_AddRefs(sensorEvents)))) {
    152    return;
    153  }
    154 
    155  if (FAILED(sensor->SetEventSink(sensorEvents))) {
    156    return;
    157  }
    158 
    159  sAccelerometer = sensor;
    160 }
    161 
    162 void DisableSensorNotifications(SensorType aSensor) {
    163  if (aSensor == SENSOR_ACCELERATION && sAccelerometer) {
    164    sAccelerometer->SetEventSink(nullptr);
    165    sAccelerometer = nullptr;
    166  }
    167 }
    168 
    169 }  // namespace hal_impl
    170 }  // namespace mozilla