Apply _RELATIVE relocations ahead of others.
[chromium-blink-merge.git] / content / browser / device_sensors / sensor_manager_android.cc
blob11de85ae68cabb799855e123bf597401d787a1db
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 static void updateRotationVectorHistogram(bool value) {
20 UMA_HISTOGRAM_BOOLEAN("InertialSensor.RotationVectorAndroidAvailable", value);
25 namespace content {
27 SensorManagerAndroid::SensorManagerAndroid()
28 : number_active_device_motion_sensors_(0),
29 device_light_buffer_(NULL),
30 device_motion_buffer_(NULL),
31 device_orientation_buffer_(NULL),
32 is_light_buffer_ready_(false),
33 is_motion_buffer_ready_(false),
34 is_orientation_buffer_ready_(false),
35 is_using_backup_sensors_for_orientation_(false) {
36 memset(received_motion_data_, 0, sizeof(received_motion_data_));
37 device_sensors_.Reset(Java_DeviceSensors_getInstance(
38 AttachCurrentThread(), base::android::GetApplicationContext()));
41 SensorManagerAndroid::~SensorManagerAndroid() {
44 bool SensorManagerAndroid::Register(JNIEnv* env) {
45 return RegisterNativesImpl(env);
48 SensorManagerAndroid* SensorManagerAndroid::GetInstance() {
49 return Singleton<SensorManagerAndroid,
50 LeakySingletonTraits<SensorManagerAndroid> >::get();
53 void SensorManagerAndroid::GotOrientation(
54 JNIEnv*, jobject, double alpha, double beta, double gamma) {
55 base::AutoLock autolock(orientation_buffer_lock_);
57 if (!device_orientation_buffer_)
58 return;
60 device_orientation_buffer_->seqlock.WriteBegin();
61 device_orientation_buffer_->data.alpha = alpha;
62 device_orientation_buffer_->data.hasAlpha = true;
63 device_orientation_buffer_->data.beta = beta;
64 device_orientation_buffer_->data.hasBeta = true;
65 device_orientation_buffer_->data.gamma = gamma;
66 device_orientation_buffer_->data.hasGamma = true;
67 device_orientation_buffer_->seqlock.WriteEnd();
69 if (!is_orientation_buffer_ready_) {
70 SetOrientationBufferReadyStatus(true);
71 updateRotationVectorHistogram(!is_using_backup_sensors_for_orientation_);
75 void SensorManagerAndroid::GotAcceleration(
76 JNIEnv*, jobject, double x, double y, double z) {
77 base::AutoLock autolock(motion_buffer_lock_);
79 if (!device_motion_buffer_)
80 return;
82 device_motion_buffer_->seqlock.WriteBegin();
83 device_motion_buffer_->data.accelerationX = x;
84 device_motion_buffer_->data.hasAccelerationX = true;
85 device_motion_buffer_->data.accelerationY = y;
86 device_motion_buffer_->data.hasAccelerationY = true;
87 device_motion_buffer_->data.accelerationZ = z;
88 device_motion_buffer_->data.hasAccelerationZ = true;
89 device_motion_buffer_->seqlock.WriteEnd();
91 if (!is_motion_buffer_ready_) {
92 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
93 CheckMotionBufferReadyToRead();
97 void SensorManagerAndroid::GotAccelerationIncludingGravity(
98 JNIEnv*, jobject, double x, double y, double z) {
99 base::AutoLock autolock(motion_buffer_lock_);
101 if (!device_motion_buffer_)
102 return;
104 device_motion_buffer_->seqlock.WriteBegin();
105 device_motion_buffer_->data.accelerationIncludingGravityX = x;
106 device_motion_buffer_->data.hasAccelerationIncludingGravityX = true;
107 device_motion_buffer_->data.accelerationIncludingGravityY = y;
108 device_motion_buffer_->data.hasAccelerationIncludingGravityY = true;
109 device_motion_buffer_->data.accelerationIncludingGravityZ = z;
110 device_motion_buffer_->data.hasAccelerationIncludingGravityZ = true;
111 device_motion_buffer_->seqlock.WriteEnd();
113 if (!is_motion_buffer_ready_) {
114 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
115 CheckMotionBufferReadyToRead();
119 void SensorManagerAndroid::GotRotationRate(
120 JNIEnv*, jobject, double alpha, double beta, double gamma) {
121 base::AutoLock autolock(motion_buffer_lock_);
123 if (!device_motion_buffer_)
124 return;
126 device_motion_buffer_->seqlock.WriteBegin();
127 device_motion_buffer_->data.rotationRateAlpha = alpha;
128 device_motion_buffer_->data.hasRotationRateAlpha = true;
129 device_motion_buffer_->data.rotationRateBeta = beta;
130 device_motion_buffer_->data.hasRotationRateBeta = true;
131 device_motion_buffer_->data.rotationRateGamma = gamma;
132 device_motion_buffer_->data.hasRotationRateGamma = true;
133 device_motion_buffer_->seqlock.WriteEnd();
135 if (!is_motion_buffer_ready_) {
136 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
137 CheckMotionBufferReadyToRead();
141 void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
142 base::AutoLock autolock(light_buffer_lock_);
144 if (!device_light_buffer_)
145 return;
147 device_light_buffer_->seqlock.WriteBegin();
148 device_light_buffer_->data.value = value;
149 device_light_buffer_->seqlock.WriteEnd();
152 bool SensorManagerAndroid::Start(EventType event_type) {
153 DCHECK(!device_sensors_.is_null());
154 int rate_in_microseconds = (event_type == kTypeLight)
155 ? kLightSensorIntervalMicroseconds
156 : kInertialSensorIntervalMicroseconds;
157 return Java_DeviceSensors_start(AttachCurrentThread(),
158 device_sensors_.obj(),
159 reinterpret_cast<intptr_t>(this),
160 static_cast<jint>(event_type),
161 rate_in_microseconds);
164 void SensorManagerAndroid::Stop(EventType event_type) {
165 DCHECK(!device_sensors_.is_null());
166 Java_DeviceSensors_stop(AttachCurrentThread(),
167 device_sensors_.obj(),
168 static_cast<jint>(event_type));
171 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
172 DCHECK(!device_sensors_.is_null());
173 return Java_DeviceSensors_getNumberActiveDeviceMotionSensors(
174 AttachCurrentThread(), device_sensors_.obj());
177 bool SensorManagerAndroid::isUsingBackupSensorsForOrientation() {
178 DCHECK(!device_sensors_.is_null());
179 return Java_DeviceSensors_isUsingBackupSensorsForOrientation(
180 AttachCurrentThread(), device_sensors_.obj());
183 // ----- Shared memory API methods
185 // --- Device Light
187 bool SensorManagerAndroid::StartFetchingDeviceLightData(
188 DeviceLightHardwareBuffer* buffer) {
189 DCHECK(buffer);
191 base::AutoLock autolock(light_buffer_lock_);
192 device_light_buffer_ = buffer;
193 SetLightBufferValue(-1);
195 bool success = Start(kTypeLight);
196 if (!success) {
197 base::AutoLock autolock(light_buffer_lock_);
198 SetLightBufferValue(std::numeric_limits<double>::infinity());
200 return success;
203 void SensorManagerAndroid::StopFetchingDeviceLightData() {
204 Stop(kTypeLight);
206 base::AutoLock autolock(light_buffer_lock_);
207 if (device_light_buffer_) {
208 SetLightBufferValue(-1);
209 device_light_buffer_ = NULL;
214 void SensorManagerAndroid::SetLightBufferValue(double lux) {
215 device_light_buffer_->seqlock.WriteBegin();
216 device_light_buffer_->data.value = lux;
217 device_light_buffer_->seqlock.WriteEnd();
219 // --- Device Motion
221 bool SensorManagerAndroid::StartFetchingDeviceMotionData(
222 DeviceMotionHardwareBuffer* buffer) {
223 DCHECK(buffer);
225 base::AutoLock autolock(motion_buffer_lock_);
226 device_motion_buffer_ = buffer;
227 ClearInternalMotionBuffers();
229 bool success = Start(kTypeMotion);
231 // If no motion data can ever be provided, the number of active device motion
232 // sensors will be zero. In that case flag the shared memory buffer
233 // as ready to read, as it will not change anyway.
234 number_active_device_motion_sensors_ = GetNumberActiveDeviceMotionSensors();
236 base::AutoLock autolock(motion_buffer_lock_);
237 CheckMotionBufferReadyToRead();
239 return success;
242 void SensorManagerAndroid::StopFetchingDeviceMotionData() {
243 Stop(kTypeMotion);
245 base::AutoLock autolock(motion_buffer_lock_);
246 if (device_motion_buffer_) {
247 ClearInternalMotionBuffers();
248 device_motion_buffer_ = NULL;
253 void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
254 if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
255 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
256 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
257 number_active_device_motion_sensors_) {
258 device_motion_buffer_->seqlock.WriteBegin();
259 device_motion_buffer_->data.interval =
260 kInertialSensorIntervalMicroseconds / 1000.;
261 device_motion_buffer_->seqlock.WriteEnd();
262 SetMotionBufferReadyStatus(true);
264 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
265 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0);
266 UMA_HISTOGRAM_BOOLEAN(
267 "InertialSensor.AccelerometerIncGravityAndroidAvailable",
268 received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY]
269 > 0);
270 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
271 received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
275 void SensorManagerAndroid::SetMotionBufferReadyStatus(bool ready) {
276 device_motion_buffer_->seqlock.WriteBegin();
277 device_motion_buffer_->data.allAvailableSensorsAreActive = ready;
278 device_motion_buffer_->seqlock.WriteEnd();
279 is_motion_buffer_ready_ = ready;
282 void SensorManagerAndroid::ClearInternalMotionBuffers() {
283 memset(received_motion_data_, 0, sizeof(received_motion_data_));
284 number_active_device_motion_sensors_ = 0;
285 SetMotionBufferReadyStatus(false);
288 // --- Device Orientation
290 void SensorManagerAndroid::SetOrientationBufferReadyStatus(bool ready) {
291 device_orientation_buffer_->seqlock.WriteBegin();
292 device_orientation_buffer_->data.absolute = ready;
293 device_orientation_buffer_->data.hasAbsolute = ready;
294 device_orientation_buffer_->data.allAvailableSensorsAreActive = ready;
295 device_orientation_buffer_->seqlock.WriteEnd();
296 is_orientation_buffer_ready_ = ready;
299 bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
300 DeviceOrientationHardwareBuffer* buffer) {
301 DCHECK(buffer);
303 base::AutoLock autolock(orientation_buffer_lock_);
304 device_orientation_buffer_ = buffer;
306 bool success = Start(kTypeOrientation);
309 base::AutoLock autolock(orientation_buffer_lock_);
310 // If Start() was unsuccessful then set the buffer ready flag to true
311 // to start firing all-null events.
312 SetOrientationBufferReadyStatus(!success);
315 if (!success)
316 updateRotationVectorHistogram(false);
317 else
318 is_using_backup_sensors_for_orientation_ =
319 isUsingBackupSensorsForOrientation();
321 return success;
324 void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
325 Stop(kTypeOrientation);
327 base::AutoLock autolock(orientation_buffer_lock_);
328 if (device_orientation_buffer_) {
329 SetOrientationBufferReadyStatus(false);
330 device_orientation_buffer_ = NULL;
335 } // namespace content