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 "content/browser/device_sensors/data_fetcher_shared_memory.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/metrics/histogram_macros.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "content/browser/device_sensors/ambient_light_mac.h" | |
13 #include "device/sensors/public/cpp/device_util_mac.h" | |
14 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" | |
15 | |
16 namespace { | |
17 | |
18 const double kMeanGravity = 9.80665; | |
19 | |
20 void FetchLight(content::AmbientLightSensor* sensor, | |
21 content::DeviceLightHardwareBuffer* buffer) { | |
22 DCHECK(sensor); | |
23 DCHECK(buffer); | |
24 // Macbook pro has 2 lux values, left and right, we take the average. | |
25 // The raw sensor values are converted to lux using LMUvalueToLux(raw_value) | |
26 // similar to how it is done in Firefox. | |
27 uint64_t lux_value[2]; | |
28 if (!sensor->ReadSensorValue(lux_value)) | |
29 return; | |
30 uint64_t mean = (lux_value[0] + lux_value[1]) / 2; | |
31 double lux = device::LMUvalueToLux(mean); | |
32 buffer->seqlock.WriteBegin(); | |
33 buffer->data.value = lux; | |
34 buffer->seqlock.WriteEnd(); | |
35 } | |
36 | |
37 void FetchMotion(SuddenMotionSensor* sensor, | |
38 content::DeviceMotionHardwareBuffer* buffer) { | |
39 DCHECK(sensor); | |
40 DCHECK(buffer); | |
41 | |
42 float axis_value[3]; | |
43 if (!sensor->ReadSensorValues(axis_value)) | |
44 return; | |
45 | |
46 buffer->seqlock.WriteBegin(); | |
47 buffer->data.accelerationIncludingGravityX = axis_value[0] * kMeanGravity; | |
48 buffer->data.hasAccelerationIncludingGravityX = true; | |
49 buffer->data.accelerationIncludingGravityY = axis_value[1] * kMeanGravity; | |
50 buffer->data.hasAccelerationIncludingGravityY = true; | |
51 buffer->data.accelerationIncludingGravityZ = axis_value[2] * kMeanGravity; | |
52 buffer->data.hasAccelerationIncludingGravityZ = true; | |
53 buffer->data.allAvailableSensorsAreActive = true; | |
54 buffer->seqlock.WriteEnd(); | |
55 } | |
56 | |
57 void FetchOrientation(SuddenMotionSensor* sensor, | |
58 content::DeviceOrientationHardwareBuffer* buffer) { | |
59 DCHECK(sensor); | |
60 DCHECK(buffer); | |
61 | |
62 // Retrieve per-axis calibrated values. | |
63 float axis_value[3]; | |
64 if (!sensor->ReadSensorValues(axis_value)) | |
65 return; | |
66 | |
67 // Transform the accelerometer values to W3C draft angles. | |
68 // | |
69 // Accelerometer values are just dot products of the sensor axes | |
70 // by the gravity vector 'g' with the result for the z axis inverted. | |
71 // | |
72 // To understand this transformation calculate the 3rd row of the z-x-y | |
73 // Euler angles rotation matrix (because of the 'g' vector, only 3rd row | |
74 // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz. | |
75 // Then, assume alpha = 0 and you get this: | |
76 // | |
77 // x_acc = sin(gamma) | |
78 // y_acc = - cos(gamma) * sin(beta) | |
79 // z_acc = cos(beta) * cos(gamma) | |
80 // | |
81 // After that the rest is just a bit of trigonometry. | |
82 // | |
83 // Also note that alpha can't be provided but it's assumed to be always zero. | |
84 // This is necessary in order to provide enough information to solve | |
85 // the equations. | |
86 // | |
87 const double kRad2deg = 180.0 / M_PI; | |
88 double beta = kRad2deg * atan2(-axis_value[1], axis_value[2]); | |
89 double gamma = kRad2deg * asin(axis_value[0]); | |
90 | |
91 // Make sure that the interval boundaries comply with the specification. At | |
92 // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has | |
93 // the upper bound open on both. | |
94 if (beta == 180.0) | |
95 beta = -180; // -180 == 180 (upside-down) | |
96 if (gamma == 90.0) | |
97 gamma = nextafter(90, 0); | |
98 | |
99 // At this point, DCHECKing is paranoia. Never hurts. | |
100 DCHECK_GE(beta, -180.0); | |
101 DCHECK_LT(beta, 180.0); | |
102 DCHECK_GE(gamma, -90.0); | |
103 DCHECK_LT(gamma, 90.0); | |
104 | |
105 buffer->seqlock.WriteBegin(); | |
106 buffer->data.beta = beta; | |
107 buffer->data.hasBeta = true; | |
108 buffer->data.gamma = gamma; | |
109 buffer->data.hasGamma = true; | |
110 buffer->data.allAvailableSensorsAreActive = true; | |
111 buffer->seqlock.WriteEnd(); | |
112 } | |
113 | |
114 } // namespace | |
115 | |
116 namespace content { | |
117 | |
118 DataFetcherSharedMemory::DataFetcherSharedMemory() { | |
119 } | |
120 | |
121 DataFetcherSharedMemory::~DataFetcherSharedMemory() { | |
122 } | |
123 | |
124 void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { | |
125 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
126 DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || | |
127 consumer_bitmask & CONSUMER_TYPE_MOTION || | |
128 consumer_bitmask & CONSUMER_TYPE_LIGHT); | |
129 | |
130 if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION) | |
131 FetchOrientation(sudden_motion_sensor_.get(), orientation_buffer_); | |
132 if (consumer_bitmask & CONSUMER_TYPE_MOTION) | |
133 FetchMotion(sudden_motion_sensor_.get(), motion_buffer_); | |
134 if (consumer_bitmask & CONSUMER_TYPE_LIGHT) | |
135 FetchLight(ambient_light_sensor_.get(), light_buffer_); | |
136 } | |
137 | |
138 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const { | |
139 return FETCHER_TYPE_POLLING_CALLBACK; | |
140 } | |
141 | |
142 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { | |
143 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
144 DCHECK(buffer); | |
145 | |
146 switch (consumer_type) { | |
147 case CONSUMER_TYPE_MOTION: { | |
148 if (!sudden_motion_sensor_) | |
149 sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); | |
150 bool sudden_motion_sensor_available = | |
151 sudden_motion_sensor_.get() != nullptr; | |
152 | |
153 motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer); | |
154 UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable", | |
155 sudden_motion_sensor_available); | |
156 if (!sudden_motion_sensor_available) { | |
157 // No motion sensor available, fire an all-null event. | |
158 motion_buffer_->seqlock.WriteBegin(); | |
159 motion_buffer_->data.allAvailableSensorsAreActive = true; | |
160 motion_buffer_->seqlock.WriteEnd(); | |
161 } | |
162 return sudden_motion_sensor_available; | |
163 } | |
164 case CONSUMER_TYPE_ORIENTATION: { | |
165 if (!sudden_motion_sensor_) | |
166 sudden_motion_sensor_.reset(SuddenMotionSensor::Create()); | |
167 bool sudden_motion_sensor_available = | |
168 sudden_motion_sensor_.get() != nullptr; | |
169 | |
170 orientation_buffer_ = | |
171 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
172 UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable", | |
173 sudden_motion_sensor_available); | |
174 if (sudden_motion_sensor_available) { | |
175 // On Mac we cannot provide absolute orientation. | |
176 orientation_buffer_->seqlock.WriteBegin(); | |
177 orientation_buffer_->data.absolute = false; | |
178 orientation_buffer_->seqlock.WriteEnd(); | |
179 } else { | |
180 // No motion sensor available, fire an all-null event. | |
181 orientation_buffer_->seqlock.WriteBegin(); | |
182 orientation_buffer_->data.allAvailableSensorsAreActive = true; | |
183 orientation_buffer_->seqlock.WriteEnd(); | |
184 } | |
185 return sudden_motion_sensor_available; | |
186 } | |
187 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: { | |
188 orientation_absolute_buffer_ = | |
189 static_cast<DeviceOrientationHardwareBuffer*>(buffer); | |
190 // Absolute device orientation not available on Mac, let the | |
191 // implementation fire an all-null event to signal this to blink. | |
192 orientation_absolute_buffer_->seqlock.WriteBegin(); | |
193 orientation_absolute_buffer_->data.absolute = true; | |
194 orientation_absolute_buffer_->data.allAvailableSensorsAreActive = true; | |
195 orientation_absolute_buffer_->seqlock.WriteEnd(); | |
196 return false; | |
197 } | |
198 case CONSUMER_TYPE_LIGHT: { | |
199 if (!ambient_light_sensor_) | |
200 ambient_light_sensor_ = AmbientLightSensor::Create(); | |
201 bool ambient_light_sensor_available = | |
202 ambient_light_sensor_.get() != nullptr; | |
203 | |
204 light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer); | |
205 if (!ambient_light_sensor_available) { | |
206 light_buffer_->seqlock.WriteBegin(); | |
207 light_buffer_->data.value = std::numeric_limits<double>::infinity(); | |
208 light_buffer_->seqlock.WriteEnd(); | |
209 } | |
210 return ambient_light_sensor_available; | |
211 } | |
212 default: | |
213 NOTREACHED(); | |
214 } | |
215 return false; | |
216 } | |
217 | |
218 bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { | |
219 DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); | |
220 | |
221 switch (consumer_type) { | |
222 case CONSUMER_TYPE_MOTION: | |
223 if (motion_buffer_) { | |
224 motion_buffer_->seqlock.WriteBegin(); | |
225 motion_buffer_->data.allAvailableSensorsAreActive = false; | |
226 motion_buffer_->seqlock.WriteEnd(); | |
227 motion_buffer_ = nullptr; | |
228 } | |
229 return true; | |
230 case CONSUMER_TYPE_ORIENTATION: | |
231 if (orientation_buffer_) { | |
232 orientation_buffer_->seqlock.WriteBegin(); | |
233 orientation_buffer_->data.allAvailableSensorsAreActive = false; | |
234 orientation_buffer_->seqlock.WriteEnd(); | |
235 orientation_buffer_ = nullptr; | |
236 } | |
237 return true; | |
238 case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: | |
239 if (orientation_absolute_buffer_) { | |
240 orientation_absolute_buffer_->seqlock.WriteBegin(); | |
241 orientation_absolute_buffer_->data.allAvailableSensorsAreActive = false; | |
242 orientation_absolute_buffer_->seqlock.WriteEnd(); | |
243 orientation_absolute_buffer_ = nullptr; | |
244 } | |
245 return true; | |
246 case CONSUMER_TYPE_LIGHT: | |
247 if (light_buffer_) { | |
248 light_buffer_->seqlock.WriteBegin(); | |
249 light_buffer_->data.value = -1; | |
250 light_buffer_->seqlock.WriteEnd(); | |
251 light_buffer_ = nullptr; | |
252 } | |
253 return true; | |
254 default: | |
255 NOTREACHED(); | |
256 } | |
257 return false; | |
258 } | |
259 | |
260 } // namespace content | |
OLD | NEW |