Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / device_sensors / sensor_manager_android.cc
blobf63e45a91ffa16af1a793d70664bce5c71dd3a73
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.
5 #include "content/browser/device_sensors/sensor_manager_android.h"
7 #include <string.h>
9 #include "base/android/jni_android.h"
10 #include "base/bind.h"
11 #include "base/memory/singleton.h"
12 #include "base/metrics/histogram.h"
13 #include "content/browser/device_sensors/inertial_sensor_consts.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "jni/DeviceSensors_jni.h"
17 using base::android::AttachCurrentThread;
19 namespace {
21 enum OrientationSensorType {
22 NOT_AVAILABLE = 0,
23 ROTATION_VECTOR = 1,
24 ACCELEROMETER_MAGNETIC = 2,
25 ORIENTATION_SENSOR_MAX = 3,
28 void UpdateDeviceOrientationHistogram(OrientationSensorType type) {
29 UMA_HISTOGRAM_ENUMERATION("InertialSensor.DeviceOrientationSensorAndroid",
30 type,
31 ORIENTATION_SENSOR_MAX);
34 } // namespace
36 namespace content {
38 SensorManagerAndroid::SensorManagerAndroid()
39 : number_active_device_motion_sensors_(0),
40 device_light_buffer_(nullptr),
41 device_motion_buffer_(nullptr),
42 device_orientation_buffer_(nullptr),
43 is_light_buffer_ready_(false),
44 is_motion_buffer_ready_(false),
45 is_orientation_buffer_ready_(false),
46 is_using_backup_sensors_for_orientation_(false),
47 is_shutdown_(false) {
48 memset(received_motion_data_, 0, sizeof(received_motion_data_));
49 device_sensors_.Reset(Java_DeviceSensors_getInstance(
50 AttachCurrentThread(), base::android::GetApplicationContext()));
53 SensorManagerAndroid::~SensorManagerAndroid() {
56 bool SensorManagerAndroid::Register(JNIEnv* env) {
57 return RegisterNativesImpl(env);
60 SensorManagerAndroid* SensorManagerAndroid::GetInstance() {
61 return Singleton<SensorManagerAndroid,
62 LeakySingletonTraits<SensorManagerAndroid> >::get();
65 void SensorManagerAndroid::GotOrientation(
66 JNIEnv*, jobject, double alpha, double beta, double gamma) {
67 base::AutoLock autolock(orientation_buffer_lock_);
69 if (!device_orientation_buffer_)
70 return;
72 device_orientation_buffer_->seqlock.WriteBegin();
73 device_orientation_buffer_->data.alpha = alpha;
74 device_orientation_buffer_->data.hasAlpha = true;
75 device_orientation_buffer_->data.beta = beta;
76 device_orientation_buffer_->data.hasBeta = true;
77 device_orientation_buffer_->data.gamma = gamma;
78 device_orientation_buffer_->data.hasGamma = true;
79 device_orientation_buffer_->seqlock.WriteEnd();
81 if (!is_orientation_buffer_ready_) {
82 SetOrientationBufferReadyStatus(true);
83 UpdateDeviceOrientationHistogram(is_using_backup_sensors_for_orientation_
84 ? ACCELEROMETER_MAGNETIC : ROTATION_VECTOR);
88 void SensorManagerAndroid::GotAcceleration(
89 JNIEnv*, jobject, double x, double y, double z) {
90 base::AutoLock autolock(motion_buffer_lock_);
92 if (!device_motion_buffer_)
93 return;
95 device_motion_buffer_->seqlock.WriteBegin();
96 device_motion_buffer_->data.accelerationX = x;
97 device_motion_buffer_->data.hasAccelerationX = true;
98 device_motion_buffer_->data.accelerationY = y;
99 device_motion_buffer_->data.hasAccelerationY = true;
100 device_motion_buffer_->data.accelerationZ = z;
101 device_motion_buffer_->data.hasAccelerationZ = true;
102 device_motion_buffer_->seqlock.WriteEnd();
104 if (!is_motion_buffer_ready_) {
105 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
106 CheckMotionBufferReadyToRead();
110 void SensorManagerAndroid::GotAccelerationIncludingGravity(
111 JNIEnv*, jobject, double x, double y, double z) {
112 base::AutoLock autolock(motion_buffer_lock_);
114 if (!device_motion_buffer_)
115 return;
117 device_motion_buffer_->seqlock.WriteBegin();
118 device_motion_buffer_->data.accelerationIncludingGravityX = x;
119 device_motion_buffer_->data.hasAccelerationIncludingGravityX = true;
120 device_motion_buffer_->data.accelerationIncludingGravityY = y;
121 device_motion_buffer_->data.hasAccelerationIncludingGravityY = true;
122 device_motion_buffer_->data.accelerationIncludingGravityZ = z;
123 device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true;
124 device_motion_buffer_->seqlock.WriteEnd();
126 if (!is_motion_buffer_ready_) {
127 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
128 CheckMotionBufferReadyToRead();
132 void SensorManagerAndroid::GotRotationRate(
133 JNIEnv*, jobject, double alpha, double beta, double gamma) {
134 base::AutoLock autolock(motion_buffer_lock_);
136 if (!device_motion_buffer_)
137 return;
139 device_motion_buffer_->seqlock.WriteBegin();
140 device_motion_buffer_->data.rotationRateAlpha = alpha;
141 device_motion_buffer_->data.hasRotationRateAlpha = true;
142 device_motion_buffer_->data.rotationRateBeta = beta;
143 device_motion_buffer_->data.hasRotationRateBeta = true;
144 device_motion_buffer_->data.rotationRateGamma = gamma;
145 device_motion_buffer_->data.hasRotationRateGamma = true;
146 device_motion_buffer_->seqlock.WriteEnd();
148 if (!is_motion_buffer_ready_) {
149 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
150 CheckMotionBufferReadyToRead();
154 void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
155 base::AutoLock autolock(light_buffer_lock_);
157 if (!device_light_buffer_)
158 return;
160 device_light_buffer_->seqlock.WriteBegin();
161 device_light_buffer_->data.value = value;
162 device_light_buffer_->seqlock.WriteEnd();
165 bool SensorManagerAndroid::Start(EventType event_type) {
166 DCHECK(!device_sensors_.is_null());
167 int rate_in_microseconds = (event_type == kTypeLight)
168 ? kLightSensorIntervalMicroseconds
169 : kInertialSensorIntervalMicroseconds;
170 return Java_DeviceSensors_start(AttachCurrentThread(),
171 device_sensors_.obj(),
172 reinterpret_cast<intptr_t>(this),
173 static_cast<jint>(event_type),
174 rate_in_microseconds);
177 void SensorManagerAndroid::Stop(EventType event_type) {
178 DCHECK(!device_sensors_.is_null());
179 Java_DeviceSensors_stop(AttachCurrentThread(),
180 device_sensors_.obj(),
181 static_cast<jint>(event_type));
184 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
185 DCHECK(!device_sensors_.is_null());
186 return Java_DeviceSensors_getNumberActiveDeviceMotionSensors(
187 AttachCurrentThread(), device_sensors_.obj());
190 bool SensorManagerAndroid::isUsingBackupSensorsForOrientation() {
191 DCHECK(!device_sensors_.is_null());
192 return Java_DeviceSensors_isUsingBackupSensorsForOrientation(
193 AttachCurrentThread(), device_sensors_.obj());
196 // ----- Shared memory API methods
198 // --- Device Light
200 bool SensorManagerAndroid::StartFetchingDeviceLightData(
201 DeviceLightHardwareBuffer* buffer) {
202 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
203 StartFetchingLightDataOnUI(buffer);
204 } else {
205 BrowserThread::PostTask(
206 BrowserThread::UI, FROM_HERE,
207 base::Bind(&SensorManagerAndroid::StartFetchingLightDataOnUI,
208 base::Unretained(this),
209 buffer));
211 return true;
214 void SensorManagerAndroid::StartFetchingLightDataOnUI(
215 DeviceLightHardwareBuffer* buffer) {
216 DCHECK_CURRENTLY_ON(BrowserThread::UI);
217 DCHECK(buffer);
218 if (is_shutdown_)
219 return;
222 base::AutoLock autolock(light_buffer_lock_);
223 device_light_buffer_ = buffer;
224 SetLightBufferValue(-1);
226 bool success = Start(kTypeLight);
227 if (!success) {
228 base::AutoLock autolock(light_buffer_lock_);
229 SetLightBufferValue(std::numeric_limits<double>::infinity());
233 void SensorManagerAndroid::StopFetchingDeviceLightData() {
234 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
235 StopFetchingLightDataOnUI();
236 return;
239 BrowserThread::PostTask(
240 BrowserThread::UI, FROM_HERE,
241 base::Bind(&SensorManagerAndroid::StopFetchingLightDataOnUI,
242 base::Unretained(this)));
245 void SensorManagerAndroid::StopFetchingLightDataOnUI() {
246 DCHECK_CURRENTLY_ON(BrowserThread::UI);
247 if (is_shutdown_)
248 return;
250 Stop(kTypeLight);
252 base::AutoLock autolock(light_buffer_lock_);
253 if (device_light_buffer_) {
254 SetLightBufferValue(-1);
255 device_light_buffer_ = nullptr;
260 void SensorManagerAndroid::SetLightBufferValue(double lux) {
261 device_light_buffer_->seqlock.WriteBegin();
262 device_light_buffer_->data.value = lux;
263 device_light_buffer_->seqlock.WriteEnd();
266 // --- Device Motion
268 bool SensorManagerAndroid::StartFetchingDeviceMotionData(
269 DeviceMotionHardwareBuffer* buffer) {
270 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
271 StartFetchingMotionDataOnUI(buffer);
272 } else {
273 BrowserThread::PostTask(
274 BrowserThread::UI, FROM_HERE,
275 base::Bind(&SensorManagerAndroid::StartFetchingMotionDataOnUI,
276 base::Unretained(this),
277 buffer));
279 return true;
282 void SensorManagerAndroid::StartFetchingMotionDataOnUI(
283 DeviceMotionHardwareBuffer* buffer) {
284 DCHECK_CURRENTLY_ON(BrowserThread::UI);
285 DCHECK(buffer);
286 if (is_shutdown_)
287 return;
290 base::AutoLock autolock(motion_buffer_lock_);
291 device_motion_buffer_ = buffer;
292 ClearInternalMotionBuffers();
294 Start(kTypeMotion);
296 // If no motion data can ever be provided, the number of active device motion
297 // sensors will be zero. In that case flag the shared memory buffer
298 // as ready to read, as it will not change anyway.
299 number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors();
301 base::AutoLock autolock(motion_buffer_lock_);
302 CheckMotionBufferReadyToRead();
306 void SensorManagerAndroid::StopFetchingDeviceMotionData() {
307 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
308 StopFetchingMotionDataOnUI();
309 return;
312 BrowserThread::PostTask(
313 BrowserThread::UI, FROM_HERE,
314 base::Bind(&SensorManagerAndroid::StopFetchingMotionDataOnUI,
315 base::Unretained(this)));
318 void SensorManagerAndroid::StopFetchingMotionDataOnUI() {
319 DCHECK_CURRENTLY_ON(BrowserThread::UI);
320 if (is_shutdown_)
321 return;
323 Stop(kTypeMotion);
325 base::AutoLock autolock(motion_buffer_lock_);
326 if (device_motion_buffer_) {
327 ClearInternalMotionBuffers();
328 device_motion_buffer_ = nullptr;
333 void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
334 if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
335 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
336 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
337 number_active_device_motion_sensors_) {
338 device_motion_buffer_->seqlock.WriteBegin();
339 device_motion_buffer_->data.interval =
340 kInertialSensorIntervalMicroseconds / 1000.;
341 device_motion_buffer_->seqlock.WriteEnd();
342 SetMotionBufferReadyStatus(true);
344 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
345 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0);
346 UMA_HISTOGRAM_BOOLEAN(
347 "InertialSensor.AccelerometerIncGravityAndroidAvailable",
348 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY]
349 > 0);
350 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
351 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
355 void SensorManagerAndroid::SetMotionBufferReadyStatus(bool ready) {
356 device_motion_buffer_->seqlock.WriteBegin();
357 device_motion_buffer_->data.allAvailableSensorsAreActive = ready;
358 device_motion_buffer_->seqlock.WriteEnd();
359 is_motion_buffer_ready_ = ready;
362 void SensorManagerAndroid::ClearInternalMotionBuffers() {
363 memset(received_motion_data_, 0, sizeof(received_motion_data_));
364 number_active_device_motion_sensors_ = 0;
365 SetMotionBufferReadyStatus(false);
368 // --- Device Orientation
370 void SensorManagerAndroid::SetOrientationBufferReadyStatus(bool ready) {
371 device_orientation_buffer_->seqlock.WriteBegin();
372 device_orientation_buffer_->data.absolute = ready;
373 device_orientation_buffer_->data.hasAbsolute = ready;
374 device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
375 device_orientation_buffer_->seqlock.WriteEnd();
376 is_orientation_buffer_ready_ = ready;
379 bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
380 DeviceOrientationHardwareBuffer* buffer) {
381 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
382 StartFetchingOrientationDataOnUI(buffer);
383 } else {
384 BrowserThread::PostTask(
385 BrowserThread::UI, FROM_HERE,
386 base::Bind(&SensorManagerAndroid::StartFetchingOrientationDataOnUI,
387 base::Unretained(this),
388 buffer));
390 return true;
393 void SensorManagerAndroid::StartFetchingOrientationDataOnUI(
394 DeviceOrientationHardwareBuffer* buffer) {
395 DCHECK_CURRENTLY_ON(BrowserThread::UI);
396 DCHECK(buffer);
397 if (is_shutdown_)
398 return;
401 base::AutoLock autolock(orientation_buffer_lock_);
402 device_orientation_buffer_ = buffer;
404 bool success = Start(kTypeOrientation);
407 base::AutoLock autolock(orientation_buffer_lock_);
408 // If Start() was unsuccessful then set the buffer ready flag to true
409 // to start firing all-null events.
410 SetOrientationBufferReadyStatus(!success);
413 if (!success) {
414 UpdateDeviceOrientationHistogram(NOT_AVAILABLE);
415 } else {
416 is_using_backup_sensors_for_orientation_ =
417 isUsingBackupSensorsForOrientation();
421 void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
422 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
423 StopFetchingOrientationDataOnUI();
424 return;
427 BrowserThread::PostTask(
428 BrowserThread::UI, FROM_HERE,
429 base::Bind(&SensorManagerAndroid::StopFetchingOrientationDataOnUI,
430 base::Unretained(this)));
433 void SensorManagerAndroid::StopFetchingOrientationDataOnUI() {
434 DCHECK_CURRENTLY_ON(BrowserThread::UI);
435 if (is_shutdown_)
436 return;
438 Stop(kTypeOrientation);
440 base::AutoLock autolock(orientation_buffer_lock_);
441 if (device_orientation_buffer_) {
442 SetOrientationBufferReadyStatus(false);
443 device_orientation_buffer_ = nullptr;
448 void SensorManagerAndroid::Shutdown() {
449 DCHECK_CURRENTLY_ON(BrowserThread::UI);
450 is_shutdown_ = true;
453 } // namespace content