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