Refactors gesture conversion functions to ui/events/blink
[chromium-blink-merge.git] / content / browser / device_sensors / data_fetcher_shared_memory_win.cc
blob8abd447b82c0c000d6e3b83e873cb8b104cb28c8
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/device_sensors/data_fetcher_shared_memory.h"
7 #include <GuidDef.h>
8 #include <InitGuid.h>
9 #include <PortableDeviceTypes.h>
10 #include <Sensors.h>
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/win/iunknown_impl.h"
15 #include "base/win/windows_version.h"
17 namespace {
19 const double kMeanGravity = 9.80665;
21 void SetLightBuffer(content::DeviceLightHardwareBuffer* buffer, double lux) {
22 DCHECK(buffer);
23 buffer->seqlock.WriteBegin();
24 buffer->data.value = lux;
25 buffer->seqlock.WriteEnd();
28 } // namespace
31 namespace content {
33 class DataFetcherSharedMemory::SensorEventSink
34 : public ISensorEvents, public base::win::IUnknownImpl {
35 public:
36 SensorEventSink() {}
37 virtual ~SensorEventSink() {}
39 // IUnknown interface
40 ULONG STDMETHODCALLTYPE AddRef() override {
41 return IUnknownImpl::AddRef();
44 ULONG STDMETHODCALLTYPE Release() override {
45 return IUnknownImpl::Release();
48 STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override {
49 if (riid == __uuidof(ISensorEvents)) {
50 *ppv = static_cast<ISensorEvents*>(this);
51 AddRef();
52 return S_OK;
54 return IUnknownImpl::QueryInterface(riid, ppv);
57 // ISensorEvents interface
58 STDMETHODIMP OnEvent(ISensor* sensor,
59 REFGUID event_id,
60 IPortableDeviceValues* event_data) override {
61 return S_OK;
64 STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) override {
65 return S_OK;
68 STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) override {
69 return S_OK;
72 STDMETHODIMP OnDataUpdated(ISensor* sensor,
73 ISensorDataReport* new_data) override {
74 if (nullptr == new_data || nullptr == sensor)
75 return E_INVALIDARG;
76 return UpdateSharedMemoryBuffer(sensor, new_data) ? S_OK : E_FAIL;
79 protected:
80 virtual bool UpdateSharedMemoryBuffer(
81 ISensor* sensor, ISensorDataReport* new_data) = 0;
83 void GetSensorValue(REFPROPERTYKEY property, ISensorDataReport* new_data,
84 double* value, bool* has_value) {
85 PROPVARIANT variant_value = {};
86 if (SUCCEEDED(new_data->GetSensorValue(property, &variant_value))) {
87 if (variant_value.vt == VT_R8)
88 *value = variant_value.dblVal;
89 else if (variant_value.vt == VT_R4)
90 *value = variant_value.fltVal;
91 *has_value = true;
92 } else {
93 *value = 0;
94 *has_value = false;
98 private:
100 DISALLOW_COPY_AND_ASSIGN(SensorEventSink);
103 class DataFetcherSharedMemory::SensorEventSinkOrientation
104 : public DataFetcherSharedMemory::SensorEventSink {
105 public:
106 explicit SensorEventSinkOrientation(
107 DeviceOrientationHardwareBuffer* const buffer) : buffer_(buffer) {}
108 virtual ~SensorEventSinkOrientation() {}
110 protected:
111 bool UpdateSharedMemoryBuffer(
112 ISensor* sensor, ISensorDataReport* new_data) override {
113 double alpha, beta, gamma;
114 bool has_alpha, has_beta, has_gamma;
116 GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, new_data, &alpha,
117 &has_alpha);
118 GetSensorValue(SENSOR_DATA_TYPE_TILT_Y_DEGREES, new_data, &beta,
119 &has_beta);
120 GetSensorValue(SENSOR_DATA_TYPE_TILT_Z_DEGREES, new_data, &gamma,
121 &has_gamma);
123 if (buffer_) {
124 buffer_->seqlock.WriteBegin();
125 buffer_->data.alpha = alpha;
126 buffer_->data.hasAlpha = has_alpha;
127 buffer_->data.beta = beta;
128 buffer_->data.hasBeta = has_beta;
129 buffer_->data.gamma = gamma;
130 buffer_->data.hasGamma = has_gamma;
131 buffer_->data.absolute = true;
132 buffer_->data.hasAbsolute = has_alpha || has_beta || has_gamma;
133 buffer_->data.allAvailableSensorsAreActive = true;
134 buffer_->seqlock.WriteEnd();
137 return true;
140 private:
141 DeviceOrientationHardwareBuffer* const buffer_;
143 DISALLOW_COPY_AND_ASSIGN(SensorEventSinkOrientation);
146 class DataFetcherSharedMemory::SensorEventSinkMotion
147 : public DataFetcherSharedMemory::SensorEventSink {
148 public:
149 explicit SensorEventSinkMotion(DeviceMotionHardwareBuffer* const buffer)
150 : buffer_(buffer) {}
151 virtual ~SensorEventSinkMotion() {}
153 protected:
154 bool UpdateSharedMemoryBuffer(
155 ISensor* sensor, ISensorDataReport* new_data) override {
157 SENSOR_TYPE_ID sensor_type = GUID_NULL;
158 if (!SUCCEEDED(sensor->GetType(&sensor_type)))
159 return false;
161 if (IsEqualIID(sensor_type, SENSOR_TYPE_ACCELEROMETER_3D)) {
162 double acceleration_including_gravity_x;
163 double acceleration_including_gravity_y;
164 double acceleration_including_gravity_z;
165 bool has_acceleration_including_gravity_x;
166 bool has_acceleration_including_gravity_y;
167 bool has_acceleration_including_gravity_z;
169 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, new_data,
170 &acceleration_including_gravity_x,
171 &has_acceleration_including_gravity_x);
172 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, new_data,
173 &acceleration_including_gravity_y,
174 &has_acceleration_including_gravity_y);
175 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, new_data,
176 &acceleration_including_gravity_z,
177 &has_acceleration_including_gravity_z);
179 if (buffer_) {
180 buffer_->seqlock.WriteBegin();
181 buffer_->data.accelerationIncludingGravityX =
182 -acceleration_including_gravity_x * kMeanGravity;
183 buffer_->data.hasAccelerationIncludingGravityX =
184 has_acceleration_including_gravity_x;
185 buffer_->data.accelerationIncludingGravityY =
186 -acceleration_including_gravity_y * kMeanGravity;
187 buffer_->data.hasAccelerationIncludingGravityY =
188 has_acceleration_including_gravity_y;
189 buffer_->data.accelerationIncludingGravityZ =
190 -acceleration_including_gravity_z * kMeanGravity;
191 buffer_->data.hasAccelerationIncludingGravityZ =
192 has_acceleration_including_gravity_z;
193 // TODO(timvolodine): consider setting this after all
194 // sensors have fired.
195 buffer_->data.allAvailableSensorsAreActive = true;
196 buffer_->seqlock.WriteEnd();
199 } else if (IsEqualIID(sensor_type, SENSOR_TYPE_GYROMETER_3D)) {
200 double alpha, beta, gamma;
201 bool has_alpha, has_beta, has_gamma;
203 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND,
204 new_data, &alpha, &has_alpha);
205 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND,
206 new_data, &beta, &has_beta);
207 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND,
208 new_data, &gamma, &has_gamma);
210 if (buffer_) {
211 buffer_->seqlock.WriteBegin();
212 buffer_->data.rotationRateAlpha = alpha;
213 buffer_->data.hasRotationRateAlpha = has_alpha;
214 buffer_->data.rotationRateBeta = beta;
215 buffer_->data.hasRotationRateBeta = has_beta;
216 buffer_->data.rotationRateGamma = gamma;
217 buffer_->data.hasRotationRateGamma = has_gamma;
218 buffer_->data.allAvailableSensorsAreActive = true;
219 buffer_->seqlock.WriteEnd();
223 return true;
226 private:
227 DeviceMotionHardwareBuffer* const buffer_;
229 DISALLOW_COPY_AND_ASSIGN(SensorEventSinkMotion);
232 class DataFetcherSharedMemory::SensorEventSinkLight
233 : public DataFetcherSharedMemory::SensorEventSink {
234 public:
235 explicit SensorEventSinkLight(DeviceLightHardwareBuffer* const buffer)
236 : buffer_(buffer) {}
237 virtual ~SensorEventSinkLight() {}
239 protected:
240 bool UpdateSharedMemoryBuffer(ISensor* sensor,
241 ISensorDataReport* new_data) override {
242 double lux;
243 bool has_lux;
245 GetSensorValue(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, new_data, &lux, &has_lux);
247 if(!has_lux) {
248 // Could not get lux value.
249 return false;
252 SetLightBuffer(buffer_, lux);
254 return true;
257 private:
258 DeviceLightHardwareBuffer* const buffer_;
260 DISALLOW_COPY_AND_ASSIGN(SensorEventSinkLight);
263 DataFetcherSharedMemory::DataFetcherSharedMemory()
264 : motion_buffer_(nullptr),
265 orientation_buffer_(nullptr),
266 light_buffer_(nullptr) {
269 DataFetcherSharedMemory::~DataFetcherSharedMemory() {
272 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const {
273 return FETCHER_TYPE_SEPARATE_THREAD;
276 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
277 DCHECK(buffer);
279 switch (consumer_type) {
280 case CONSUMER_TYPE_ORIENTATION:
282 orientation_buffer_ =
283 static_cast<DeviceOrientationHardwareBuffer*>(buffer);
284 scoped_refptr<SensorEventSink> sink(
285 new SensorEventSinkOrientation(orientation_buffer_));
286 bool inclinometer_available = RegisterForSensor(
287 SENSOR_TYPE_INCLINOMETER_3D, sensor_inclinometer_.Receive(), sink);
288 UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable",
289 inclinometer_available);
290 if (inclinometer_available)
291 return true;
292 // if no sensors are available set buffer to ready, to fire null-events.
293 SetBufferAvailableState(consumer_type, true);
295 break;
296 case CONSUMER_TYPE_MOTION:
298 motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
299 scoped_refptr<SensorEventSink> sink(
300 new SensorEventSinkMotion(motion_buffer_));
301 bool accelerometer_available = RegisterForSensor(
302 SENSOR_TYPE_ACCELEROMETER_3D, sensor_accelerometer_.Receive(),
303 sink);
304 bool gyrometer_available = RegisterForSensor(
305 SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink);
306 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable",
307 accelerometer_available);
308 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable",
309 gyrometer_available);
310 if (accelerometer_available || gyrometer_available) {
311 motion_buffer_->seqlock.WriteBegin();
312 motion_buffer_->data.interval = GetInterval().InMilliseconds();
313 motion_buffer_->seqlock.WriteEnd();
314 return true;
316 // if no sensors are available set buffer to ready, to fire null-events.
317 SetBufferAvailableState(consumer_type, true);
319 break;
320 case CONSUMER_TYPE_LIGHT:
322 light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer);
323 scoped_refptr<SensorEventSink> sink(
324 new SensorEventSinkLight(light_buffer_));
325 bool sensor_light_available = RegisterForSensor(
326 SENSOR_TYPE_AMBIENT_LIGHT, sensor_light_.Receive(), sink);
327 if (sensor_light_available) {
328 SetLightBuffer(light_buffer_, -1);
329 return true;
332 // if no sensors are available, fire an Infinity event.
333 SetLightBuffer(light_buffer_, std::numeric_limits<double>::infinity());
335 break;
336 default:
337 NOTREACHED();
339 return false;
342 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
343 DisableSensors(consumer_type);
344 SetBufferAvailableState(consumer_type, false);
345 switch (consumer_type) {
346 case CONSUMER_TYPE_ORIENTATION:
347 orientation_buffer_ = nullptr;
348 return true;
349 case CONSUMER_TYPE_MOTION:
350 motion_buffer_ = nullptr;
351 return true;
352 case CONSUMER_TYPE_LIGHT:
353 SetLightBuffer(light_buffer_, -1);
354 light_buffer_ = nullptr;
355 return true;
356 default:
357 NOTREACHED();
359 return false;
362 bool DataFetcherSharedMemory::RegisterForSensor(
363 REFSENSOR_TYPE_ID sensor_type,
364 ISensor** sensor,
365 scoped_refptr<SensorEventSink> event_sink) {
366 if (base::win::GetVersion() < base::win::VERSION_WIN7)
367 return false;
369 base::win::ScopedComPtr<ISensorManager> sensor_manager;
370 HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager);
371 if (FAILED(hr) || !sensor_manager.get())
372 return false;
374 base::win::ScopedComPtr<ISensorCollection> sensor_collection;
375 hr = sensor_manager->GetSensorsByType(
376 sensor_type, sensor_collection.Receive());
378 if (FAILED(hr) || !sensor_collection.get())
379 return false;
381 ULONG count = 0;
382 hr = sensor_collection->GetCount(&count);
383 if (FAILED(hr) || !count)
384 return false;
386 hr = sensor_collection->GetAt(0, sensor);
387 if (FAILED(hr) || !(*sensor))
388 return false;
390 base::win::ScopedComPtr<IPortableDeviceValues> device_values;
391 if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) {
392 if (SUCCEEDED(device_values->SetUnsignedIntegerValue(
393 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
394 GetInterval().InMilliseconds()))) {
395 base::win::ScopedComPtr<IPortableDeviceValues> return_values;
396 (*sensor)->SetProperties(device_values.get(), return_values.Receive());
400 base::win::ScopedComPtr<ISensorEvents> sensor_events;
401 hr = event_sink->QueryInterface(
402 __uuidof(ISensorEvents), sensor_events.ReceiveVoid());
403 if (FAILED(hr) || !sensor_events.get())
404 return false;
406 hr = (*sensor)->SetEventSink(sensor_events.get());
407 if (FAILED(hr))
408 return false;
410 return true;
413 void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) {
414 switch(consumer_type) {
415 case CONSUMER_TYPE_ORIENTATION:
416 if (sensor_inclinometer_.get()) {
417 sensor_inclinometer_->SetEventSink(nullptr);
418 sensor_inclinometer_.Release();
420 break;
421 case CONSUMER_TYPE_MOTION:
422 if (sensor_accelerometer_.get()) {
423 sensor_accelerometer_->SetEventSink(nullptr);
424 sensor_accelerometer_.Release();
426 if (sensor_gyrometer_.get()) {
427 sensor_gyrometer_->SetEventSink(nullptr);
428 sensor_gyrometer_.Release();
430 break;
431 case CONSUMER_TYPE_LIGHT:
432 if (sensor_light_.get()) {
433 sensor_light_->SetEventSink(nullptr);
434 sensor_light_.Release();
436 break;
437 default:
438 NOTREACHED();
442 void DataFetcherSharedMemory::SetBufferAvailableState(
443 ConsumerType consumer_type, bool enabled) {
444 switch(consumer_type) {
445 case CONSUMER_TYPE_ORIENTATION:
446 if (orientation_buffer_) {
447 orientation_buffer_->seqlock.WriteBegin();
448 orientation_buffer_->data.allAvailableSensorsAreActive = enabled;
449 orientation_buffer_->seqlock.WriteEnd();
451 break;
452 case CONSUMER_TYPE_MOTION:
453 if (motion_buffer_) {
454 motion_buffer_->seqlock.WriteBegin();
455 motion_buffer_->data.allAvailableSensorsAreActive = enabled;
456 motion_buffer_->seqlock.WriteEnd();
458 break;
459 default:
460 NOTREACHED();
464 } // namespace content