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