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_orientation/sensor_manager_android.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_orientation/inertial_sensor_consts.h"
13 #include "jni/DeviceMotionAndOrientation_jni.h"
15 using base::android::AttachCurrentThread
;
19 static void updateRotationVectorHistogram(bool value
) {
20 UMA_HISTOGRAM_BOOLEAN("InertialSensor.RotationVectorAndroidAvailable", value
);
27 SensorManagerAndroid::SensorManagerAndroid()
28 : number_active_device_motion_sensors_(0),
29 device_motion_buffer_(NULL
),
30 device_orientation_buffer_(NULL
),
31 is_motion_buffer_ready_(false),
32 is_orientation_buffer_ready_(false) {
33 memset(received_motion_data_
, 0, sizeof(received_motion_data_
));
34 device_orientation_
.Reset(
35 Java_DeviceMotionAndOrientation_getInstance(
36 AttachCurrentThread(),
37 base::android::GetApplicationContext()));
40 SensorManagerAndroid::~SensorManagerAndroid() {
43 bool SensorManagerAndroid::Register(JNIEnv
* env
) {
44 return RegisterNativesImpl(env
);
47 SensorManagerAndroid
* SensorManagerAndroid::GetInstance() {
48 return Singleton
<SensorManagerAndroid
,
49 LeakySingletonTraits
<SensorManagerAndroid
> >::get();
52 void SensorManagerAndroid::GotOrientation(
53 JNIEnv
*, jobject
, double alpha
, double beta
, double gamma
) {
54 base::AutoLock
autolock(orientation_buffer_lock_
);
56 if (!device_orientation_buffer_
)
59 device_orientation_buffer_
->seqlock
.WriteBegin();
60 device_orientation_buffer_
->data
.alpha
= alpha
;
61 device_orientation_buffer_
->data
.hasAlpha
= true;
62 device_orientation_buffer_
->data
.beta
= beta
;
63 device_orientation_buffer_
->data
.hasBeta
= true;
64 device_orientation_buffer_
->data
.gamma
= gamma
;
65 device_orientation_buffer_
->data
.hasGamma
= true;
66 device_orientation_buffer_
->seqlock
.WriteEnd();
68 if (!is_orientation_buffer_ready_
) {
69 SetOrientationBufferReadyStatus(true);
70 updateRotationVectorHistogram(true);
74 void SensorManagerAndroid::GotAcceleration(
75 JNIEnv
*, jobject
, double x
, double y
, double z
) {
76 base::AutoLock
autolock(motion_buffer_lock_
);
78 if (!device_motion_buffer_
)
81 device_motion_buffer_
->seqlock
.WriteBegin();
82 device_motion_buffer_
->data
.accelerationX
= x
;
83 device_motion_buffer_
->data
.hasAccelerationX
= true;
84 device_motion_buffer_
->data
.accelerationY
= y
;
85 device_motion_buffer_
->data
.hasAccelerationY
= true;
86 device_motion_buffer_
->data
.accelerationZ
= z
;
87 device_motion_buffer_
->data
.hasAccelerationZ
= true;
88 device_motion_buffer_
->seqlock
.WriteEnd();
90 if (!is_motion_buffer_ready_
) {
91 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] = 1;
92 CheckMotionBufferReadyToRead();
96 void SensorManagerAndroid::GotAccelerationIncludingGravity(
97 JNIEnv
*, jobject
, double x
, double y
, double z
) {
98 base::AutoLock
autolock(motion_buffer_lock_
);
100 if (!device_motion_buffer_
)
103 device_motion_buffer_
->seqlock
.WriteBegin();
104 device_motion_buffer_
->data
.accelerationIncludingGravityX
= x
;
105 device_motion_buffer_
->data
.hasAccelerationIncludingGravityX
= true;
106 device_motion_buffer_
->data
.accelerationIncludingGravityY
= y
;
107 device_motion_buffer_
->data
.hasAccelerationIncludingGravityY
= true;
108 device_motion_buffer_
->data
.accelerationIncludingGravityZ
= z
;
109 device_motion_buffer_
->data
.hasAccelerationIncludingGravityZ
= true;
110 device_motion_buffer_
->seqlock
.WriteEnd();
112 if (!is_motion_buffer_ready_
) {
113 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
] = 1;
114 CheckMotionBufferReadyToRead();
118 void SensorManagerAndroid::GotRotationRate(
119 JNIEnv
*, jobject
, double alpha
, double beta
, double gamma
) {
120 base::AutoLock
autolock(motion_buffer_lock_
);
122 if (!device_motion_buffer_
)
125 device_motion_buffer_
->seqlock
.WriteBegin();
126 device_motion_buffer_
->data
.rotationRateAlpha
= alpha
;
127 device_motion_buffer_
->data
.hasRotationRateAlpha
= true;
128 device_motion_buffer_
->data
.rotationRateBeta
= beta
;
129 device_motion_buffer_
->data
.hasRotationRateBeta
= true;
130 device_motion_buffer_
->data
.rotationRateGamma
= gamma
;
131 device_motion_buffer_
->data
.hasRotationRateGamma
= true;
132 device_motion_buffer_
->seqlock
.WriteEnd();
134 if (!is_motion_buffer_ready_
) {
135 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] = 1;
136 CheckMotionBufferReadyToRead();
140 bool SensorManagerAndroid::Start(EventType event_type
) {
141 DCHECK(!device_orientation_
.is_null());
142 return Java_DeviceMotionAndOrientation_start(
143 AttachCurrentThread(), device_orientation_
.obj(),
144 reinterpret_cast<intptr_t>(this), static_cast<jint
>(event_type
),
145 kInertialSensorIntervalMillis
);
148 void SensorManagerAndroid::Stop(EventType event_type
) {
149 DCHECK(!device_orientation_
.is_null());
150 Java_DeviceMotionAndOrientation_stop(
151 AttachCurrentThread(), device_orientation_
.obj(),
152 static_cast<jint
>(event_type
));
155 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
156 DCHECK(!device_orientation_
.is_null());
157 return Java_DeviceMotionAndOrientation_getNumberActiveDeviceMotionSensors(
158 AttachCurrentThread(), device_orientation_
.obj());
162 // ----- Shared memory API methods
166 bool SensorManagerAndroid::StartFetchingDeviceMotionData(
167 DeviceMotionHardwareBuffer
* buffer
) {
170 base::AutoLock
autolock(motion_buffer_lock_
);
171 device_motion_buffer_
= buffer
;
172 ClearInternalMotionBuffers();
174 bool success
= Start(kTypeMotion
);
176 // If no motion data can ever be provided, the number of active device motion
177 // sensors will be zero. In that case flag the shared memory buffer
178 // as ready to read, as it will not change anyway.
179 number_active_device_motion_sensors_
= GetNumberActiveDeviceMotionSensors();
181 base::AutoLock
autolock(motion_buffer_lock_
);
182 CheckMotionBufferReadyToRead();
187 void SensorManagerAndroid::StopFetchingDeviceMotionData() {
190 base::AutoLock
autolock(motion_buffer_lock_
);
191 if (device_motion_buffer_
) {
192 ClearInternalMotionBuffers();
193 device_motion_buffer_
= NULL
;
198 void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
199 if (received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] +
200 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
] +
201 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] ==
202 number_active_device_motion_sensors_
) {
203 device_motion_buffer_
->seqlock
.WriteBegin();
204 device_motion_buffer_
->data
.interval
= kInertialSensorIntervalMillis
;
205 device_motion_buffer_
->seqlock
.WriteEnd();
206 SetMotionBufferReadyStatus(true);
208 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
209 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] > 0);
210 UMA_HISTOGRAM_BOOLEAN(
211 "InertialSensor.AccelerometerIncGravityAndroidAvailable",
212 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
]
214 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
215 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] > 0);
219 void SensorManagerAndroid::SetMotionBufferReadyStatus(bool ready
) {
220 device_motion_buffer_
->seqlock
.WriteBegin();
221 device_motion_buffer_
->data
.allAvailableSensorsAreActive
= ready
;
222 device_motion_buffer_
->seqlock
.WriteEnd();
223 is_motion_buffer_ready_
= ready
;
226 void SensorManagerAndroid::ClearInternalMotionBuffers() {
227 memset(received_motion_data_
, 0, sizeof(received_motion_data_
));
228 number_active_device_motion_sensors_
= 0;
229 SetMotionBufferReadyStatus(false);
232 // --- Device Orientation
234 void SensorManagerAndroid::SetOrientationBufferReadyStatus(bool ready
) {
235 device_orientation_buffer_
->seqlock
.WriteBegin();
236 device_orientation_buffer_
->data
.absolute
= ready
;
237 device_orientation_buffer_
->data
.hasAbsolute
= ready
;
238 device_orientation_buffer_
->data
.allAvailableSensorsAreActive
= ready
;
239 device_orientation_buffer_
->seqlock
.WriteEnd();
240 is_orientation_buffer_ready_
= ready
;
243 bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
244 DeviceOrientationHardwareBuffer
* buffer
) {
247 base::AutoLock
autolock(orientation_buffer_lock_
);
248 device_orientation_buffer_
= buffer
;
250 bool success
= Start(kTypeOrientation
);
253 base::AutoLock
autolock(orientation_buffer_lock_
);
254 // If Start() was unsuccessful then set the buffer ready flag to true
255 // to start firing all-null events.
256 SetOrientationBufferReadyStatus(!success
);
260 updateRotationVectorHistogram(false);
265 void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
266 Stop(kTypeOrientation
);
268 base::AutoLock
autolock(orientation_buffer_lock_
);
269 if (device_orientation_buffer_
) {
270 SetOrientationBufferReadyStatus(false);
271 device_orientation_buffer_
= NULL
;
276 } // namespace content