Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / device_sensors / sensor_manager_android.cc
blob49750b075d5f5d73dad416e730360283a4b01f1f
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/memory/singleton.h"
11 #include "base/metrics/histogram.h"
12 #include "content/browser/device_sensors/inertial_sensor_consts.h"
13 #include "jni/DeviceSensors_jni.h"
15 using base::android::AttachCurrentThread;
17 namespace {
19 enum OrientationSensorType {
20 NOT_AVAILABLE = 0,
21 ROTATION_VECTOR = 1,
22 ACCELEROMETER_MAGNETIC = 2,
23 ORIENTATION_SENSOR_MAX = 3,
26 static void UpdateDeviceOrientationHistogram(OrientationSensorType type) {
27 UMA_HISTOGRAM_ENUMERATION("InertialSensor.DeviceOrientationSensorAndroid",
28 type,
29 ORIENTATION_SENSOR_MAX);
34 namespace content {
36 SensorManagerAndroid::SensorManagerAndroid()
37 : number_active_device_motion_sensors_(0),
38 device_light_buffer_(NULL),
39 device_motion_buffer_(NULL),
40 device_orientation_buffer_(NULL),
41 is_light_buffer_ready_(false),
42 is_motion_buffer_ready_(false),
43 is_orientation_buffer_ready_(false),
44 is_using_backup_sensors_for_orientation_(false) {
45 memset(received_motion_data_, 0, sizeof(received_motion_data_));
46 device_sensors_.Reset(Java_DeviceSensors_getInstance(
47 AttachCurrentThread(), base::android::GetApplicationContext()));
50 SensorManagerAndroid::~SensorManagerAndroid() {
53 bool SensorManagerAndroid::Register(JNIEnv* env) {
54 return RegisterNativesImpl(env);
57 SensorManagerAndroid* SensorManagerAndroid::GetInstance() {
58 return Singleton<SensorManagerAndroid,
59 LeakySingletonTraits<SensorManagerAndroid> >::get();
62 void SensorManagerAndroid::GotOrientation(
63 JNIEnv*, jobject, double alpha, double beta, double gamma) {
64 base::AutoLock autolock(orientation_buffer_lock_);
66 if (!device_orientation_buffer_)
67 return;
69 device_orientation_buffer_->seqlock.WriteBegin();
70 device_orientation_buffer_->data.alpha = alpha;
71 device_orientation_buffer_->data.hasAlpha = true;
72 device_orientation_buffer_->data.beta = beta;
73 device_orientation_buffer_->data.hasBeta = true;
74 device_orientation_buffer_->data.gamma = gamma;
75 device_orientation_buffer_->data.hasGamma = true;
76 device_orientation_buffer_->seqlock.WriteEnd();
78 if (!is_orientation_buffer_ready_) {
79 SetOrientationBufferReadyStatus(true);
80 UpdateDeviceOrientationHistogram(is_using_backup_sensors_for_orientation_
81 ? ACCELEROMETER_MAGNETIC : ROTATION_VECTOR);
85 void SensorManagerAndroid::GotAcceleration(
86 JNIEnv*, jobject, double x, double y, double z) {
87 base::AutoLock autolock(motion_buffer_lock_);
89 if (!device_motion_buffer_)
90 return;
92 device_motion_buffer_->seqlock.WriteBegin();
93 device_motion_buffer_->data.accelerationX = x;
94 device_motion_buffer_->data.hasAccelerationX = true;
95 device_motion_buffer_->data.accelerationY = y;
96 device_motion_buffer_->data.hasAccelerationY = true;
97 device_motion_buffer_->data.accelerationZ = z;
98 device_motion_buffer_->data.hasAccelerationZ = true;
99 device_motion_buffer_->seqlock.WriteEnd();
101 if (!is_motion_buffer_ready_) {
102 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
103 CheckMotionBufferReadyToRead();
107 void SensorManagerAndroid::GotAccelerationIncludingGravity(
108 JNIEnv*, jobject, double x, double y, double z) {
109 base::AutoLock autolock(motion_buffer_lock_);
111 if (!device_motion_buffer_)
112 return;
114 device_motion_buffer_->seqlock.WriteBegin();
115 device_motion_buffer_->data.accelerationIncludingGravityX = x;
116 device_motion_buffer_->data.hasAccelerationIncludingGravityX = true;
117 device_motion_buffer_->data.accelerationIncludingGravityY = y;
118 device_motion_buffer_->data.hasAccelerationIncludingGravityY = true;
119 device_motion_buffer_->data.accelerationIncludingGravityZ = z;
120 device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true;
121 device_motion_buffer_->seqlock.WriteEnd();
123 if (!is_motion_buffer_ready_) {
124 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
125 CheckMotionBufferReadyToRead();
129 void SensorManagerAndroid::GotRotationRate(
130 JNIEnv*, jobject, double alpha, double beta, double gamma) {
131 base::AutoLock autolock(motion_buffer_lock_);
133 if (!device_motion_buffer_)
134 return;
136 device_motion_buffer_->seqlock.WriteBegin();
137 device_motion_buffer_->data.rotationRateAlpha = alpha;
138 device_motion_buffer_->data.hasRotationRateAlpha = true;
139 device_motion_buffer_->data.rotationRateBeta = beta;
140 device_motion_buffer_->data.hasRotationRateBeta = true;
141 device_motion_buffer_->data.rotationRateGamma = gamma;
142 device_motion_buffer_->data.hasRotationRateGamma = true;
143 device_motion_buffer_->seqlock.WriteEnd();
145 if (!is_motion_buffer_ready_) {
146 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
147 CheckMotionBufferReadyToRead();
151 void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
152 base::AutoLock autolock(light_buffer_lock_);
154 if (!device_light_buffer_)
155 return;
157 device_light_buffer_->seqlock.WriteBegin();
158 device_light_buffer_->data.value = value;
159 device_light_buffer_->seqlock.WriteEnd();
162 bool SensorManagerAndroid::Start(EventType event_type) {
163 DCHECK(!device_sensors_.is_null());
164 int rate_in_microseconds = (event_type == kTypeLight)
165 ? kLightSensorIntervalMicroseconds
166 : kInertialSensorIntervalMicroseconds;
167 return Java_DeviceSensors_start(AttachCurrentThread(),
168 device_sensors_.obj(),
169 reinterpret_cast<intptr_t>(this),
170 static_cast<jint>(event_type),
171 rate_in_microseconds);
174 void SensorManagerAndroid::Stop(EventType event_type) {
175 DCHECK(!device_sensors_.is_null());
176 Java_DeviceSensors_stop(AttachCurrentThread(),
177 device_sensors_.obj(),
178 static_cast<jint>(event_type));
181 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
182 DCHECK(!device_sensors_.is_null());
183 return Java_DeviceSensors_getNumberActiveDeviceMotionSensors(
184 AttachCurrentThread(), device_sensors_.obj());
187 bool SensorManagerAndroid::isUsingBackupSensorsForOrientation() {
188 DCHECK(!device_sensors_.is_null());
189 return Java_DeviceSensors_isUsingBackupSensorsForOrientation(
190 AttachCurrentThread(), device_sensors_.obj());
193 // ----- Shared memory API methods
195 // --- Device Light
197 bool SensorManagerAndroid::StartFetchingDeviceLightData(
198 DeviceLightHardwareBuffer* buffer) {
199 DCHECK(buffer);
201 base::AutoLock autolock(light_buffer_lock_);
202 device_light_buffer_ = buffer;
203 SetLightBufferValue(-1);
205 bool success = Start(kTypeLight);
206 if (!success) {
207 base::AutoLock autolock(light_buffer_lock_);
208 SetLightBufferValue(std::numeric_limits<double>::infinity());
210 return success;
213 void SensorManagerAndroid::StopFetchingDeviceLightData() {
214 Stop(kTypeLight);
216 base::AutoLock autolock(light_buffer_lock_);
217 if (device_light_buffer_) {
218 SetLightBufferValue(-1);
219 device_light_buffer_ = NULL;
224 void SensorManagerAndroid::SetLightBufferValue(double lux) {
225 device_light_buffer_->seqlock.WriteBegin();
226 device_light_buffer_->data.value = lux;
227 device_light_buffer_->seqlock.WriteEnd();
229 // --- Device Motion
231 bool SensorManagerAndroid::StartFetchingDeviceMotionData(
232 DeviceMotionHardwareBuffer* buffer) {
233 DCHECK(buffer);
235 base::AutoLock autolock(motion_buffer_lock_);
236 device_motion_buffer_ = buffer;
237 ClearInternalMotionBuffers();
239 bool success = Start(kTypeMotion);
241 // If no motion data can ever be provided, the number of active device motion
242 // sensors will be zero. In that case flag the shared memory buffer
243 // as ready to read, as it will not change anyway.
244 number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors();
246 base::AutoLock autolock(motion_buffer_lock_);
247 CheckMotionBufferReadyToRead();
249 return success;
252 void SensorManagerAndroid::StopFetchingDeviceMotionData() {
253 Stop(kTypeMotion);
255 base::AutoLock autolock(motion_buffer_lock_);
256 if (device_motion_buffer_) {
257 ClearInternalMotionBuffers();
258 device_motion_buffer_ = NULL;
263 void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
264 if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
265 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
266 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
267 number_active_device_motion_sensors_) {
268 device_motion_buffer_->seqlock.WriteBegin();
269 device_motion_buffer_->data.interval =
270 kInertialSensorIntervalMicroseconds / 1000.;
271 device_motion_buffer_->seqlock.WriteEnd();
272 SetMotionBufferReadyStatus(true);
274 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
275 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0);
276 UMA_HISTOGRAM_BOOLEAN(
277 "InertialSensor.AccelerometerIncGravityAndroidAvailable",
278 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY]
279 > 0);
280 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
281 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
285 void SensorManagerAndroid::SetMotionBufferReadyStatus(bool ready) {
286 device_motion_buffer_->seqlock.WriteBegin();
287 device_motion_buffer_->data.allAvailableSensorsAreActive = ready;
288 device_motion_buffer_->seqlock.WriteEnd();
289 is_motion_buffer_ready_ = ready;
292 void SensorManagerAndroid::ClearInternalMotionBuffers() {
293 memset(received_motion_data_, 0, sizeof(received_motion_data_));
294 number_active_device_motion_sensors_ = 0;
295 SetMotionBufferReadyStatus(false);
298 // --- Device Orientation
300 void SensorManagerAndroid::SetOrientationBufferReadyStatus(bool ready) {
301 device_orientation_buffer_->seqlock.WriteBegin();
302 device_orientation_buffer_->data.absolute = ready;
303 device_orientation_buffer_->data.hasAbsolute = ready;
304 device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
305 device_orientation_buffer_->seqlock.WriteEnd();
306 is_orientation_buffer_ready_ = ready;
309 bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
310 DeviceOrientationHardwareBuffer* buffer) {
311 DCHECK(buffer);
313 base::AutoLock autolock(orientation_buffer_lock_);
314 device_orientation_buffer_ = buffer;
316 bool success = Start(kTypeOrientation);
319 base::AutoLock autolock(orientation_buffer_lock_);
320 // If Start() was unsuccessful then set the buffer ready flag to true
321 // to start firing all-null events.
322 SetOrientationBufferReadyStatus(!success);
325 if (!success) {
326 UpdateDeviceOrientationHistogram(NOT_AVAILABLE);
327 } else {
328 is_using_backup_sensors_for_orientation_ =
329 isUsingBackupSensorsForOrientation();
332 return success;
335 void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
336 Stop(kTypeOrientation);
338 base::AutoLock autolock(orientation_buffer_lock_);
339 if (device_orientation_buffer_) {
340 SetOrientationBufferReadyStatus(false);
341 device_orientation_buffer_ = NULL;
346 } // namespace content