OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "device/sensors/data_fetcher_shared_memory.h" | |
6 | |
7 #include <GuidDef.h> | |
8 #include <InitGuid.h> | |
9 #include <PortableDeviceTypes.h> | |
10 #include <Sensors.h> | |
11 #include <objbase.h> | |
12 | |
13 #include "base/logging.h" | |
14 #include "base/macros.h" | |
15 #include "base/metrics/histogram_macros.h" | |
16 #include "base/win/iunknown_impl.h" | |
17 #include "base/win/windows_version.h" | |
18 | |
19 namespace { | |
20 | |
21 const double kMeanGravity = 9.80665; | |
22 | |
23 } // namespace | |
24 | |
25 namespace device { | |
26 | |
27 class DataFetcherSharedMemory::SensorEventSink | |
28 : public ISensorEvents, | |
29 public base::win::IUnknownImpl { | |
30 public: | |
31 SensorEventSink() {} | |
32 ~SensorEventSink() override {} | |
33 | |
34 // IUnknown interface | |
35 ULONG STDMETHODCALLTYPE AddRef() override { return IUnknownImpl::AddRef(); } | |
36 | |
37 ULONG STDMETHODCALLTYPE Release() override { return IUnknownImpl::Release(); } | |
38 | |
39 STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override { | |
40 if (riid == __uuidof(ISensorEvents)) { | |
41 *ppv = static_cast<ISensorEvents*>(this); | |
42 AddRef(); | |
43 return S_OK; | |
44 } | |
45 return IUnknownImpl::QueryInterface(riid, ppv); | |
46 } | |
47 | |
48 // ISensorEvents interface | |
49 STDMETHODIMP OnEvent(ISensor* sensor, | |
50 REFGUID event_id, | |
51 IPortableDeviceValues* event_data) override { | |
52 return S_OK; | |
53 } | |
54 | |
55 STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) override { return S_OK; } | |
56 | |
57 STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) override { | |
58 return S_OK; | |
59 } | |
60 | |
61 STDMETHODIMP OnDataUpdated(ISensor* sensor, | |
62 ISensorDataReport* new_data) override { | |
63 if (nullptr == new_data || nullptr == sensor) | |
64 return E_INVALIDARG; | |
65 return UpdateSharedMemoryBuffer(sensor, new_data) ? S_OK : E_FAIL; | |
66 } | |
67 | |
68 protected: | |
69 virtual bool UpdateSharedMemoryBuffer(ISensor* sensor, | |
70 ISensorDataReport* new_data) = 0; | |
71 | |
72 void GetSensorValue(REFPROPERTYKEY property, | |
73 ISensorDataReport* new_data, | |
74 double* value, | |
75 bool* has_value) { | |
76 PROPVARIANT variant_value = {}; | |
77 if (SUCCEEDED(new_data->GetSensorValue(property, &variant_value))) { | |
78 if (variant_value.vt == VT_R8) | |
79 *value = variant_value.dblVal; | |
80 else if (variant_value.vt == VT_R4) | |
81 *value = variant_value.fltVal; | |
82 *has_value = true; | |
83 } else { | |
84 *value = 0; | |
85 *has_value = false; | |
86 } | |
87 } | |
88 | |
89 private: | |
90 DISALLOW_COPY_AND_ASSIGN(SensorEventSink); | |
91 }; | |
92 | |
93 class DataFetcherSharedMemory::SensorEventSinkOrientation | |
94 : public DataFetcherSharedMemory::SensorEventSink { | |
95 public: | |
96 explicit SensorEventSinkOrientation( | |
97 DeviceOrientationHardwareBuffer* const buffer) | |
98 : buffer_(buffer) {} | |
99 ~SensorEventSinkOrientation() override {} | |
100 | |
101 protected: | |
102 bool UpdateSharedMemoryBuffer(ISensor* sensor, | |
103 ISensorDataReport* new_data) override { | |
104 double alpha, beta, gamma; | |
105 bool has_alpha, has_beta, has_gamma; | |
106 | |
107 GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, new_data, &beta, &has_beta); | |
108 GetSensorValue(SENSOR_DATA_TYPE_TILT_Y_DEGREES, new_data, &gamma, | |
109 &has_gamma); | |
110 GetSensorValue(SENSOR_DATA_TYPE_TILT_Z_DEGREES, new_data, &alpha, | |
111 &has_alpha); | |
112 | |
113 if (buffer_) { | |
114 buffer_->seqlock.WriteBegin(); | |
115 buffer_->data.alpha = alpha; | |
116 buffer_->data.has_alpha = has_alpha; | |
117 buffer_->data.beta = beta; | |
118 buffer_->data.has_beta = has_beta; | |
119 buffer_->data.gamma = gamma; | |
120 buffer_->data.has_gamma = has_gamma; | |
121 buffer_->data.absolute = has_alpha || has_beta || has_gamma; | |
122 buffer_->data.all_available_sensors_are_active = true; | |
123 buffer_->seqlock.WriteEnd(); | |
124 } | |
125 | |
126 return true; | |
127 } | |
128 | |
129 private: | |
130 DeviceOrientationHardwareBuffer* const buffer_; | |
131 | |
132 DISALLOW_COPY_AND_ASSIGN(SensorEventSinkOrientation); | |
133 }; | |
134 | |
135 class DataFetcherSharedMemory::SensorEventSinkMotion | |
136 : public DataFetcherSharedMemory::SensorEventSink { | |
137 public: | |
138 explicit SensorEventSinkMotion(DeviceMotionHardwareBuffer* const buffer) | |
139 : buffer_(buffer) {} | |
140 ~SensorEventSinkMotion() override {} | |
141 | |
142 protected: | |
143 bool UpdateSharedMemoryBuffer(ISensor* sensor, | |
144 ISensorDataReport* new_data) override { | |
145 SENSOR_TYPE_ID sensor_type = GUID_NULL; | |
146 if (!SUCCEEDED(sensor->GetType(&sensor_type))) | |
147 return false; | |
148 | |
149 if (IsEqualIID(sensor_type, SENSOR_TYPE_ACCELEROMETER_3D)) { | |
150 double acceleration_including_gravity_x; | |
151 double acceleration_including_gravity_y; | |
152 double acceleration_including_gravity_z; | |
153 bool has_acceleration_including_gravity_x; | |
154 bool has_acceleration_including_gravity_y; | |
155 bool has_acceleration_including_gravity_z; | |
156 | |
157 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, new_data, | |
158 &acceleration_including_gravity_x, | |
159 &has_acceleration_including_gravity_x); | |
160 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, new_data, | |
161 &acceleration_including_gravity_y, | |
162 &has_acceleration_including_gravity_y); | |
163 GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, new_data, | |
164 &acceleration_including_gravity_z, | |
165 &has_acceleration_including_gravity_z); | |
166 | |
167 if (buffer_) { | |
168 buffer_->seqlock.WriteBegin(); | |
169 buffer_->data.acceleration_including_gravity_x = | |
170 -acceleration_including_gravity_x * kMeanGravity; | |
171 buffer_->data.has_acceleration_including_gravity_x = | |
172 has_acceleration_including_gravity_x; | |
173 buffer_->data.acceleration_including_gravity_y = | |
174 -acceleration_including_gravity_y * kMeanGravity; | |
175 buffer_->data.has_acceleration_including_gravity_y = | |
176 has_acceleration_including_gravity_y; | |
177 buffer_->data.acceleration_including_gravity_z = | |
178 -acceleration_including_gravity_z * kMeanGravity; | |
179 buffer_->data.has_acceleration_including_gravity_z = | |
180 has_acceleration_including_gravity_z; | |
181 // TODO(timvolodine): consider setting this after all | |
182 // sensors have fired. | |
183 buffer_->data.all_available_sensors_are_active = true; | |
184 buffer_->seqlock.WriteEnd(); | |
185 } | |
186 | |
187 } else if (IsEqualIID(sensor_type, SENSOR_TYPE_GYROMETER_3D)) { | |
188 double alpha, beta, gamma; | |
189 bool has_alpha, has_beta, has_gamma; | |
190 | |
191 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, | |
192 new_data, &alpha, &has_alpha); | |
193 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, | |
194 new_data, &beta, &has_beta); | |
195 GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, | |
196 new_data, &gamma, &has_gamma); | |
197 | |
198 if (buffer_) { | |
199 buffer_->seqlock.WriteBegin(); | |
200 buffer_->data.rotation_rate_alpha = alpha; | |
201 buffer_->data.has_rotation_rate_alpha = has_alpha; | |
202 buffer_->data.rotation_rate_beta = beta; | |
203 buffer_->data.has_rotation_rate_beta = has_beta; | |
204 buffer_->data.rotation_rate_gamma = gamma; | |
205 buffer_->data.has_rotation_rate_gamma = has_gamma; | |
206 buffer_->data.all_available_sensors_are_active = true; | |
207 buffer_->seqlock.WriteEnd(); | |
208 } | |
209 } | |
210 | |
211 return true; | |
212 } | |
213 | |
214 private: | |
215 DeviceMotionHardwareBuffer* const buffer_; | |
216 | |
217 DISALLOW_COPY_AND_ASSIGN(SensorEventSinkMotion); | |
218 }; | |
219 | |
220 DataFetcherSharedMemory::DataFetcherSharedMemory() {} | |
221 | |
222 DataFetcherSharedMemory::~DataFetcherSharedMemory() {} | |
223 | |
224 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { | |
225 return FETCHER_TYPE_SEPARATE_THREAD; | |
226 } | |
227 | |
228 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { | |
229 DCHECK(buffer); | |
230 | |
231 switch (consumer_type) { | |
232 case CONSUMER_TYPE_ORIENTATION: { | |
233 orientation_buffer_ = | |
234 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
235 scoped_refptr<SensorEventSink> sink( | |
236 new SensorEventSinkOrientation(orientation_buffer_)); | |
237 bool inclinometer_available = | |
238 RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D, | |
239 sensor_inclinometer_.GetAddressOf(), sink); | |
240 UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable", | |
241 inclinometer_available); | |
242 if (inclinometer_available) | |
243 return true; | |
244 // if no sensors are available set buffer to ready, to fire null-events. | |
245 SetBufferAvailableState(consumer_type, true); | |
246 } break; | |
247 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: { | |
248 orientation_absolute_buffer_ = | |
249 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
250 scoped_refptr<SensorEventSink> sink( | |
251 new SensorEventSinkOrientation(orientation_absolute_buffer_)); | |
252 // Currently we use the same sensor as for orientation which provides | |
253 // absolute angles. | |
254 bool inclinometer_available = | |
255 RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D, | |
256 sensor_inclinometer_absolute_.GetAddressOf(), sink); | |
257 // TODO(timvolodine): consider adding UMA. | |
258 if (inclinometer_available) | |
259 return true; | |
260 // if no sensors are available set buffer to ready, to fire null-events. | |
261 SetBufferAvailableState(consumer_type, true); | |
262 } break; | |
263 case CONSUMER_TYPE_MOTION: { | |
264 motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); | |
265 scoped_refptr<SensorEventSink> sink( | |
266 new SensorEventSinkMotion(motion_buffer_)); | |
267 bool accelerometer_available = | |
268 RegisterForSensor(SENSOR_TYPE_ACCELEROMETER_3D, | |
269 sensor_accelerometer_.GetAddressOf(), sink); | |
270 bool gyrometer_available = RegisterForSensor( | |
271 SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.GetAddressOf(), sink); | |
272 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable", | |
273 accelerometer_available); | |
274 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable", | |
275 gyrometer_available); | |
276 if (accelerometer_available || gyrometer_available) { | |
277 motion_buffer_->seqlock.WriteBegin(); | |
278 motion_buffer_->data.interval = GetInterval().InMilliseconds(); | |
279 motion_buffer_->seqlock.WriteEnd(); | |
280 return true; | |
281 } | |
282 // if no sensors are available set buffer to ready, to fire null-events. | |
283 SetBufferAvailableState(consumer_type, true); | |
284 } break; | |
285 default: | |
286 NOTREACHED(); | |
287 } | |
288 return false; | |
289 } | |
290 | |
291 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { | |
292 DisableSensors(consumer_type); | |
293 switch (consumer_type) { | |
294 case CONSUMER_TYPE_ORIENTATION: | |
295 SetBufferAvailableState(consumer_type, false); | |
296 orientation_buffer_ = nullptr; | |
297 return true; | |
298 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: | |
299 SetBufferAvailableState(consumer_type, false); | |
300 orientation_absolute_buffer_ = nullptr; | |
301 return true; | |
302 case CONSUMER_TYPE_MOTION: | |
303 SetBufferAvailableState(consumer_type, false); | |
304 motion_buffer_ = nullptr; | |
305 return true; | |
306 default: | |
307 NOTREACHED(); | |
308 } | |
309 return false; | |
310 } | |
311 | |
312 bool DataFetcherSharedMemory::RegisterForSensor( | |
313 REFSENSOR_TYPE_ID sensor_type, | |
314 ISensor** sensor, | |
315 scoped_refptr<SensorEventSink> event_sink) { | |
316 if (base::win::GetVersion() < base::win::VERSION_WIN7) | |
317 return false; | |
318 | |
319 base::win::ScopedComPtr<ISensorManager> sensor_manager; | |
320 HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager); | |
321 if (FAILED(hr) || !sensor_manager.Get()) | |
322 return false; | |
323 | |
324 base::win::ScopedComPtr<ISensorCollection> sensor_collection; | |
325 hr = sensor_manager->GetSensorsByType(sensor_type, | |
326 sensor_collection.GetAddressOf()); | |
327 | |
328 if (FAILED(hr) || !sensor_collection.Get()) | |
329 return false; | |
330 | |
331 ULONG count = 0; | |
332 hr = sensor_collection->GetCount(&count); | |
333 if (FAILED(hr) || !count) | |
334 return false; | |
335 | |
336 hr = sensor_collection->GetAt(0, sensor); | |
337 if (FAILED(hr) || !(*sensor)) | |
338 return false; | |
339 | |
340 base::win::ScopedComPtr<IPortableDeviceValues> device_values; | |
341 if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) { | |
342 if (SUCCEEDED(device_values->SetUnsignedIntegerValue( | |
343 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, | |
344 GetInterval().InMilliseconds()))) { | |
345 base::win::ScopedComPtr<IPortableDeviceValues> return_values; | |
346 (*sensor)->SetProperties(device_values.Get(), | |
347 return_values.GetAddressOf()); | |
348 } | |
349 } | |
350 | |
351 base::win::ScopedComPtr<ISensorEvents> sensor_events; | |
352 hr = event_sink->QueryInterface(IID_PPV_ARGS(&sensor_events)); | |
353 if (FAILED(hr) || !sensor_events.Get()) | |
354 return false; | |
355 | |
356 hr = (*sensor)->SetEventSink(sensor_events.Get()); | |
357 if (FAILED(hr)) | |
358 return false; | |
359 | |
360 return true; | |
361 } | |
362 | |
363 void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) { | |
364 switch (consumer_type) { | |
365 case CONSUMER_TYPE_ORIENTATION: | |
366 if (sensor_inclinometer_.Get()) { | |
367 sensor_inclinometer_->SetEventSink(nullptr); | |
368 sensor_inclinometer_.Reset(); | |
369 } | |
370 break; | |
371 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: | |
372 if (sensor_inclinometer_absolute_.Get()) { | |
373 sensor_inclinometer_absolute_->SetEventSink(nullptr); | |
374 sensor_inclinometer_absolute_.Reset(); | |
375 } | |
376 break; | |
377 case CONSUMER_TYPE_MOTION: | |
378 if (sensor_accelerometer_.Get()) { | |
379 sensor_accelerometer_->SetEventSink(nullptr); | |
380 sensor_accelerometer_.Reset(); | |
381 } | |
382 if (sensor_gyrometer_.Get()) { | |
383 sensor_gyrometer_->SetEventSink(nullptr); | |
384 sensor_gyrometer_.Reset(); | |
385 } | |
386 break; | |
387 default: | |
388 NOTREACHED(); | |
389 } | |
390 } | |
391 | |
392 void DataFetcherSharedMemory::SetBufferAvailableState( | |
393 ConsumerType consumer_type, | |
394 bool enabled) { | |
395 switch (consumer_type) { | |
396 case CONSUMER_TYPE_ORIENTATION: | |
397 if (orientation_buffer_) { | |
398 orientation_buffer_->seqlock.WriteBegin(); | |
399 orientation_buffer_->data.all_available_sensors_are_active = enabled; | |
400 orientation_buffer_->seqlock.WriteEnd(); | |
401 } | |
402 break; | |
403 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: | |
404 if (orientation_absolute_buffer_) { | |
405 orientation_absolute_buffer_->seqlock.WriteBegin(); | |
406 orientation_absolute_buffer_->data.all_available_sensors_are_active = | |
407 enabled; | |
408 orientation_absolute_buffer_->seqlock.WriteEnd(); | |
409 } | |
410 break; | |
411 case CONSUMER_TYPE_MOTION: | |
412 if (motion_buffer_) { | |
413 motion_buffer_->seqlock.WriteBegin(); | |
414 motion_buffer_->data.all_available_sensors_are_active = enabled; | |
415 motion_buffer_->seqlock.WriteEnd(); | |
416 } | |
417 break; | |
418 default: | |
419 NOTREACHED(); | |
420 } | |
421 } | |
422 | |
423 } // namespace device | |
OLD | NEW |