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/sensor_manager_android.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/android/context_utils.h" | |
10 #include "base/android/jni_android.h" | |
11 #include "base/bind.h" | |
12 #include "base/memory/singleton.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/metrics/histogram_macros.h" | |
15 #include "jni/DeviceSensors_jni.h" | |
16 | |
17 using base::android::AttachCurrentThread; | |
18 using base::android::JavaParamRef; | |
19 | |
20 namespace { | |
21 | |
22 void UpdateDeviceOrientationHistogram( | |
23 content::SensorManagerAndroid::OrientationSensorType type) { | |
24 UMA_HISTOGRAM_ENUMERATION("InertialSensor.DeviceOrientationSensorAndroid", | |
25 type, content::SensorManagerAndroid::ORIENTATION_SENSOR_MAX); | |
26 } | |
27 | |
28 void SetOrientation(content::DeviceOrientationHardwareBuffer* buffer, | |
29 double alpha, double beta, double gamma) { | |
30 buffer->seqlock.WriteBegin(); | |
31 buffer->data.alpha = alpha; | |
32 buffer->data.hasAlpha = true; | |
33 buffer->data.beta = beta; | |
34 buffer->data.hasBeta = true; | |
35 buffer->data.gamma = gamma; | |
36 buffer->data.hasGamma = true; | |
37 buffer->seqlock.WriteEnd(); | |
38 } | |
39 | |
40 void SetOrientationBufferStatus( | |
41 content::DeviceOrientationHardwareBuffer* buffer, | |
42 bool ready, bool absolute) { | |
43 buffer->seqlock.WriteBegin(); | |
44 buffer->data.absolute = absolute; | |
45 buffer->data.allAvailableSensorsAreActive = ready; | |
46 buffer->seqlock.WriteEnd(); | |
47 } | |
48 | |
49 } // namespace | |
50 | |
51 namespace content { | |
52 | |
53 SensorManagerAndroid::SensorManagerAndroid() | |
54 : number_active_device_motion_sensors_(0), | |
55 device_light_buffer_(nullptr), | |
56 device_motion_buffer_(nullptr), | |
57 device_orientation_buffer_(nullptr), | |
58 motion_buffer_initialized_(false), | |
59 orientation_buffer_initialized_(false), | |
60 is_shutdown_(false) { | |
61 DCHECK(thread_checker_.CalledOnValidThread()); | |
62 memset(received_motion_data_, 0, sizeof(received_motion_data_)); | |
63 device_sensors_.Reset(Java_DeviceSensors_getInstance( | |
64 AttachCurrentThread(), base::android::GetApplicationContext())); | |
65 } | |
66 | |
67 SensorManagerAndroid::~SensorManagerAndroid() { | |
68 } | |
69 | |
70 bool SensorManagerAndroid::Register(JNIEnv* env) { | |
71 return RegisterNativesImpl(env); | |
72 } | |
73 | |
74 SensorManagerAndroid* SensorManagerAndroid::GetInstance() { | |
75 DCHECK(base::MessageLoopForUI::IsCurrent()); | |
76 return base::Singleton< | |
77 SensorManagerAndroid, | |
78 base::LeakySingletonTraits<SensorManagerAndroid>>::get(); | |
79 } | |
80 | |
81 void SensorManagerAndroid::GotOrientation(JNIEnv*, | |
82 const JavaParamRef<jobject>&, | |
83 double alpha, | |
84 double beta, | |
85 double gamma) { | |
86 base::AutoLock autolock(orientation_buffer_lock_); | |
87 | |
88 if (!device_orientation_buffer_) | |
89 return; | |
90 | |
91 SetOrientation(device_orientation_buffer_, alpha, beta, gamma); | |
92 | |
93 if (!orientation_buffer_initialized_) { | |
94 OrientationSensorType type = | |
95 static_cast<OrientationSensorType>(GetOrientationSensorTypeUsed()); | |
96 SetOrientationBufferStatus(device_orientation_buffer_, true, | |
97 type != GAME_ROTATION_VECTOR); | |
98 orientation_buffer_initialized_ = true; | |
99 UpdateDeviceOrientationHistogram(type); | |
100 } | |
101 } | |
102 | |
103 void SensorManagerAndroid::GotOrientationAbsolute(JNIEnv*, | |
104 const JavaParamRef<jobject>&, | |
105 double alpha, | |
106 double beta, | |
107 double gamma) { | |
108 base::AutoLock autolock(orientation_absolute_buffer_lock_); | |
109 | |
110 if (!device_orientation_absolute_buffer_) | |
111 return; | |
112 | |
113 SetOrientation(device_orientation_absolute_buffer_, alpha, beta, gamma); | |
114 | |
115 if (!orientation_absolute_buffer_initialized_) { | |
116 SetOrientationBufferStatus(device_orientation_absolute_buffer_, true, true); | |
117 orientation_absolute_buffer_initialized_ = true; | |
118 // TODO(timvolodine): Add UMA. | |
119 } | |
120 } | |
121 | |
122 void SensorManagerAndroid::GotAcceleration(JNIEnv*, | |
123 const JavaParamRef<jobject>&, | |
124 double x, | |
125 double y, | |
126 double z) { | |
127 base::AutoLock autolock(motion_buffer_lock_); | |
128 | |
129 if (!device_motion_buffer_) | |
130 return; | |
131 | |
132 device_motion_buffer_->seqlock.WriteBegin(); | |
133 device_motion_buffer_->data.accelerationX = x; | |
134 device_motion_buffer_->data.hasAccelerationX = true; | |
135 device_motion_buffer_->data.accelerationY = y; | |
136 device_motion_buffer_->data.hasAccelerationY = true; | |
137 device_motion_buffer_->data.accelerationZ = z; | |
138 device_motion_buffer_->data.hasAccelerationZ = true; | |
139 device_motion_buffer_->seqlock.WriteEnd(); | |
140 | |
141 if (!motion_buffer_initialized_) { | |
142 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1; | |
143 CheckMotionBufferReadyToRead(); | |
144 } | |
145 } | |
146 | |
147 void SensorManagerAndroid::GotAccelerationIncludingGravity( | |
148 JNIEnv*, | |
149 const JavaParamRef<jobject>&, | |
150 double x, | |
151 double y, | |
152 double z) { | |
153 base::AutoLock autolock(motion_buffer_lock_); | |
154 | |
155 if (!device_motion_buffer_) | |
156 return; | |
157 | |
158 device_motion_buffer_->seqlock.WriteBegin(); | |
159 device_motion_buffer_->data.accelerationIncludingGravityX = x; | |
160 device_motion_buffer_->data.hasAccelerationIncludingGravityX = true; | |
161 device_motion_buffer_->data.accelerationIncludingGravityY = y; | |
162 device_motion_buffer_->data.hasAccelerationIncludingGravityY = true; | |
163 device_motion_buffer_->data.accelerationIncludingGravityZ = z; | |
164 device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true; | |
165 device_motion_buffer_->seqlock.WriteEnd(); | |
166 | |
167 if (!motion_buffer_initialized_) { | |
168 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1; | |
169 CheckMotionBufferReadyToRead(); | |
170 } | |
171 } | |
172 | |
173 void SensorManagerAndroid::GotRotationRate(JNIEnv*, | |
174 const JavaParamRef<jobject>&, | |
175 double alpha, | |
176 double beta, | |
177 double gamma) { | |
178 base::AutoLock autolock(motion_buffer_lock_); | |
179 | |
180 if (!device_motion_buffer_) | |
181 return; | |
182 | |
183 device_motion_buffer_->seqlock.WriteBegin(); | |
184 device_motion_buffer_->data.rotationRateAlpha = alpha; | |
185 device_motion_buffer_->data.hasRotationRateAlpha = true; | |
186 device_motion_buffer_->data.rotationRateBeta = beta; | |
187 device_motion_buffer_->data.hasRotationRateBeta = true; | |
188 device_motion_buffer_->data.rotationRateGamma = gamma; | |
189 device_motion_buffer_->data.hasRotationRateGamma = true; | |
190 device_motion_buffer_->seqlock.WriteEnd(); | |
191 | |
192 if (!motion_buffer_initialized_) { | |
193 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1; | |
194 CheckMotionBufferReadyToRead(); | |
195 } | |
196 } | |
197 | |
198 void SensorManagerAndroid::GotLight(JNIEnv*, | |
199 const JavaParamRef<jobject>&, | |
200 double value) { | |
201 base::AutoLock autolock(light_buffer_lock_); | |
202 | |
203 if (!device_light_buffer_) | |
204 return; | |
205 | |
206 device_light_buffer_->seqlock.WriteBegin(); | |
207 device_light_buffer_->data.value = value; | |
208 device_light_buffer_->seqlock.WriteEnd(); | |
209 } | |
210 | |
211 bool SensorManagerAndroid::Start(ConsumerType consumer_type) { | |
212 DCHECK(thread_checker_.CalledOnValidThread()); | |
213 DCHECK(!device_sensors_.is_null()); | |
214 int rate_in_microseconds = (consumer_type == CONSUMER_TYPE_LIGHT) | |
215 ? kLightSensorIntervalMicroseconds | |
216 : kDeviceSensorIntervalMicroseconds; | |
217 return Java_DeviceSensors_start( | |
218 AttachCurrentThread(), device_sensors_, reinterpret_cast<intptr_t>(this), | |
219 static_cast<jint>(consumer_type), rate_in_microseconds); | |
220 } | |
221 | |
222 void SensorManagerAndroid::Stop(ConsumerType consumer_type) { | |
223 DCHECK(thread_checker_.CalledOnValidThread()); | |
224 DCHECK(!device_sensors_.is_null()); | |
225 Java_DeviceSensors_stop(AttachCurrentThread(), device_sensors_, | |
226 static_cast<jint>(consumer_type)); | |
227 } | |
228 | |
229 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() { | |
230 DCHECK(thread_checker_.CalledOnValidThread()); | |
231 DCHECK(!device_sensors_.is_null()); | |
232 return Java_DeviceSensors_getNumberActiveDeviceMotionSensors( | |
233 AttachCurrentThread(), device_sensors_); | |
234 } | |
235 | |
236 SensorManagerAndroid::OrientationSensorType | |
237 SensorManagerAndroid::GetOrientationSensorTypeUsed() { | |
238 DCHECK(thread_checker_.CalledOnValidThread()); | |
239 DCHECK(!device_sensors_.is_null()); | |
240 return static_cast<SensorManagerAndroid::OrientationSensorType>( | |
241 Java_DeviceSensors_getOrientationSensorTypeUsed(AttachCurrentThread(), | |
242 device_sensors_)); | |
243 } | |
244 | |
245 // ----- Shared memory API methods | |
246 | |
247 // --- Device Light | |
248 | |
249 void SensorManagerAndroid::StartFetchingDeviceLightData( | |
250 DeviceLightHardwareBuffer* buffer) { | |
251 DCHECK(thread_checker_.CalledOnValidThread()); | |
252 DCHECK(buffer); | |
253 if (is_shutdown_) | |
254 return; | |
255 | |
256 { | |
257 base::AutoLock autolock(light_buffer_lock_); | |
258 device_light_buffer_ = buffer; | |
259 SetLightBufferValue(-1); | |
260 } | |
261 bool success = Start(CONSUMER_TYPE_LIGHT); | |
262 if (!success) { | |
263 base::AutoLock autolock(light_buffer_lock_); | |
264 SetLightBufferValue(std::numeric_limits<double>::infinity()); | |
265 } | |
266 } | |
267 | |
268 void SensorManagerAndroid::StopFetchingDeviceLightData() { | |
269 DCHECK(thread_checker_.CalledOnValidThread()); | |
270 if (is_shutdown_) | |
271 return; | |
272 | |
273 Stop(CONSUMER_TYPE_LIGHT); | |
274 { | |
275 base::AutoLock autolock(light_buffer_lock_); | |
276 if (device_light_buffer_) { | |
277 SetLightBufferValue(-1); | |
278 device_light_buffer_ = nullptr; | |
279 } | |
280 } | |
281 } | |
282 | |
283 void SensorManagerAndroid::SetLightBufferValue(double lux) { | |
284 device_light_buffer_->seqlock.WriteBegin(); | |
285 device_light_buffer_->data.value = lux; | |
286 device_light_buffer_->seqlock.WriteEnd(); | |
287 } | |
288 | |
289 // --- Device Motion | |
290 | |
291 void SensorManagerAndroid::StartFetchingDeviceMotionData( | |
292 DeviceMotionHardwareBuffer* buffer) { | |
293 DCHECK(thread_checker_.CalledOnValidThread()); | |
294 DCHECK(buffer); | |
295 if (is_shutdown_) | |
296 return; | |
297 | |
298 { | |
299 base::AutoLock autolock(motion_buffer_lock_); | |
300 device_motion_buffer_ = buffer; | |
301 ClearInternalMotionBuffers(); | |
302 } | |
303 Start(CONSUMER_TYPE_MOTION); | |
304 | |
305 // If no motion data can ever be provided, the number of active device motion | |
306 // sensors will be zero. In that case flag the shared memory buffer | |
307 // as ready to read, as it will not change anyway. | |
308 number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors(); | |
309 { | |
310 base::AutoLock autolock(motion_buffer_lock_); | |
311 CheckMotionBufferReadyToRead(); | |
312 } | |
313 } | |
314 | |
315 void SensorManagerAndroid::StopFetchingDeviceMotionData() { | |
316 DCHECK(thread_checker_.CalledOnValidThread()); | |
317 if (is_shutdown_) | |
318 return; | |
319 | |
320 Stop(CONSUMER_TYPE_MOTION); | |
321 { | |
322 base::AutoLock autolock(motion_buffer_lock_); | |
323 if (device_motion_buffer_) { | |
324 ClearInternalMotionBuffers(); | |
325 device_motion_buffer_ = nullptr; | |
326 } | |
327 } | |
328 } | |
329 | |
330 void SensorManagerAndroid::CheckMotionBufferReadyToRead() { | |
331 if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] + | |
332 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] + | |
333 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] == | |
334 number_active_device_motion_sensors_) { | |
335 device_motion_buffer_->seqlock.WriteBegin(); | |
336 device_motion_buffer_->data.interval = | |
337 kDeviceSensorIntervalMicroseconds / 1000.; | |
338 device_motion_buffer_->seqlock.WriteEnd(); | |
339 SetMotionBufferReadyStatus(true); | |
340 | |
341 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable", | |
342 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0); | |
343 UMA_HISTOGRAM_BOOLEAN( | |
344 "InertialSensor.AccelerometerIncGravityAndroidAvailable", | |
345 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] | |
346 > 0); | |
347 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable", | |
348 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0); | |
349 } | |
350 } | |
351 | |
352 void SensorManagerAndroid::SetMotionBufferReadyStatus(bool ready) { | |
353 device_motion_buffer_->seqlock.WriteBegin(); | |
354 device_motion_buffer_->data.allAvailableSensorsAreActive = ready; | |
355 device_motion_buffer_->seqlock.WriteEnd(); | |
356 motion_buffer_initialized_ = ready; | |
357 } | |
358 | |
359 void SensorManagerAndroid::ClearInternalMotionBuffers() { | |
360 memset(received_motion_data_, 0, sizeof(received_motion_data_)); | |
361 number_active_device_motion_sensors_ = 0; | |
362 SetMotionBufferReadyStatus(false); | |
363 } | |
364 | |
365 // --- Device Orientation | |
366 | |
367 void SensorManagerAndroid::StartFetchingDeviceOrientationData( | |
368 DeviceOrientationHardwareBuffer* buffer) { | |
369 DCHECK(thread_checker_.CalledOnValidThread()); | |
370 DCHECK(buffer); | |
371 if (is_shutdown_) | |
372 return; | |
373 | |
374 { | |
375 base::AutoLock autolock(orientation_buffer_lock_); | |
376 device_orientation_buffer_ = buffer; | |
377 } | |
378 bool success = Start(CONSUMER_TYPE_ORIENTATION); | |
379 | |
380 { | |
381 base::AutoLock autolock(orientation_buffer_lock_); | |
382 // If Start() was unsuccessful then set the buffer ready flag to true | |
383 // to start firing all-null events. | |
384 SetOrientationBufferStatus(buffer, !success /* ready */, | |
385 false /* absolute */); | |
386 orientation_buffer_initialized_ = !success; | |
387 } | |
388 | |
389 if (!success) | |
390 UpdateDeviceOrientationHistogram(NOT_AVAILABLE); | |
391 } | |
392 | |
393 void SensorManagerAndroid::StopFetchingDeviceOrientationData() { | |
394 DCHECK(thread_checker_.CalledOnValidThread()); | |
395 if (is_shutdown_) | |
396 return; | |
397 | |
398 Stop(CONSUMER_TYPE_ORIENTATION); | |
399 { | |
400 base::AutoLock autolock(orientation_buffer_lock_); | |
401 if (device_orientation_buffer_) { | |
402 SetOrientationBufferStatus(device_orientation_buffer_, false, false); | |
403 orientation_buffer_initialized_ = false; | |
404 device_orientation_buffer_ = nullptr; | |
405 } | |
406 } | |
407 } | |
408 | |
409 void SensorManagerAndroid::StartFetchingDeviceOrientationAbsoluteData( | |
410 DeviceOrientationHardwareBuffer* buffer) { | |
411 DCHECK(thread_checker_.CalledOnValidThread()); | |
412 DCHECK(buffer); | |
413 if (is_shutdown_) | |
414 return; | |
415 | |
416 { | |
417 base::AutoLock autolock(orientation_absolute_buffer_lock_); | |
418 device_orientation_absolute_buffer_ = buffer; | |
419 } | |
420 bool success = Start(CONSUMER_TYPE_ORIENTATION_ABSOLUTE); | |
421 | |
422 { | |
423 base::AutoLock autolock(orientation_absolute_buffer_lock_); | |
424 // If Start() was unsuccessful then set the buffer ready flag to true | |
425 // to start firing all-null events. | |
426 SetOrientationBufferStatus(buffer, !success /* ready */, | |
427 false /* absolute */); | |
428 orientation_absolute_buffer_initialized_ = !success; | |
429 } | |
430 } | |
431 | |
432 void SensorManagerAndroid::StopFetchingDeviceOrientationAbsoluteData() { | |
433 DCHECK(thread_checker_.CalledOnValidThread()); | |
434 if (is_shutdown_) | |
435 return; | |
436 | |
437 Stop(CONSUMER_TYPE_ORIENTATION_ABSOLUTE); | |
438 { | |
439 base::AutoLock autolock(orientation_absolute_buffer_lock_); | |
440 if (device_orientation_absolute_buffer_) { | |
441 SetOrientationBufferStatus(device_orientation_absolute_buffer_, false, | |
442 false); | |
443 orientation_absolute_buffer_initialized_ = false; | |
444 device_orientation_absolute_buffer_ = nullptr; | |
445 } | |
446 } | |
447 } | |
448 | |
449 void SensorManagerAndroid::Shutdown() { | |
450 DCHECK(thread_checker_.CalledOnValidThread()); | |
451 is_shutdown_ = true; | |
452 } | |
453 | |
454 } // namespace content | |
OLD | NEW |