| 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 |