1 // Copyright (c) 2012 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/data_fetcher_impl_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 DataFetcherImplAndroid::DataFetcherImplAndroid()
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(AttachCurrentThread()));
38 DataFetcherImplAndroid::~DataFetcherImplAndroid() {
41 bool DataFetcherImplAndroid::Register(JNIEnv
* env
) {
42 return RegisterNativesImpl(env
);
45 DataFetcherImplAndroid
* DataFetcherImplAndroid::GetInstance() {
46 return Singleton
<DataFetcherImplAndroid
,
47 LeakySingletonTraits
<DataFetcherImplAndroid
> >::get();
50 void DataFetcherImplAndroid::GotOrientation(
51 JNIEnv
*, jobject
, double alpha
, double beta
, double gamma
) {
52 base::AutoLock
autolock(orientation_buffer_lock_
);
54 if (!device_orientation_buffer_
)
57 device_orientation_buffer_
->seqlock
.WriteBegin();
58 device_orientation_buffer_
->data
.alpha
= alpha
;
59 device_orientation_buffer_
->data
.hasAlpha
= true;
60 device_orientation_buffer_
->data
.beta
= beta
;
61 device_orientation_buffer_
->data
.hasBeta
= true;
62 device_orientation_buffer_
->data
.gamma
= gamma
;
63 device_orientation_buffer_
->data
.hasGamma
= true;
64 device_orientation_buffer_
->seqlock
.WriteEnd();
66 if (!is_orientation_buffer_ready_
) {
67 SetOrientationBufferReadyStatus(true);
68 updateRotationVectorHistogram(true);
72 void DataFetcherImplAndroid::GotAcceleration(
73 JNIEnv
*, jobject
, double x
, double y
, double z
) {
74 base::AutoLock
autolock(motion_buffer_lock_
);
76 if (!device_motion_buffer_
)
79 device_motion_buffer_
->seqlock
.WriteBegin();
80 device_motion_buffer_
->data
.accelerationX
= x
;
81 device_motion_buffer_
->data
.hasAccelerationX
= true;
82 device_motion_buffer_
->data
.accelerationY
= y
;
83 device_motion_buffer_
->data
.hasAccelerationY
= true;
84 device_motion_buffer_
->data
.accelerationZ
= z
;
85 device_motion_buffer_
->data
.hasAccelerationZ
= true;
86 device_motion_buffer_
->seqlock
.WriteEnd();
88 if (!is_motion_buffer_ready_
) {
89 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] = 1;
90 CheckMotionBufferReadyToRead();
94 void DataFetcherImplAndroid::GotAccelerationIncludingGravity(
95 JNIEnv
*, jobject
, double x
, double y
, double z
) {
96 base::AutoLock
autolock(motion_buffer_lock_
);
98 if (!device_motion_buffer_
)
101 device_motion_buffer_
->seqlock
.WriteBegin();
102 device_motion_buffer_
->data
.accelerationIncludingGravityX
= x
;
103 device_motion_buffer_
->data
.hasAccelerationIncludingGravityX
= true;
104 device_motion_buffer_
->data
.accelerationIncludingGravityY
= y
;
105 device_motion_buffer_
->data
.hasAccelerationIncludingGravityY
= true;
106 device_motion_buffer_
->data
.accelerationIncludingGravityZ
= z
;
107 device_motion_buffer_
->data
.hasAccelerationIncludingGravityZ
= true;
108 device_motion_buffer_
->seqlock
.WriteEnd();
110 if (!is_motion_buffer_ready_
) {
111 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
] = 1;
112 CheckMotionBufferReadyToRead();
116 void DataFetcherImplAndroid::GotRotationRate(
117 JNIEnv
*, jobject
, double alpha
, double beta
, double gamma
) {
118 base::AutoLock
autolock(motion_buffer_lock_
);
120 if (!device_motion_buffer_
)
123 device_motion_buffer_
->seqlock
.WriteBegin();
124 device_motion_buffer_
->data
.rotationRateAlpha
= alpha
;
125 device_motion_buffer_
->data
.hasRotationRateAlpha
= true;
126 device_motion_buffer_
->data
.rotationRateBeta
= beta
;
127 device_motion_buffer_
->data
.hasRotationRateBeta
= true;
128 device_motion_buffer_
->data
.rotationRateGamma
= gamma
;
129 device_motion_buffer_
->data
.hasRotationRateGamma
= true;
130 device_motion_buffer_
->seqlock
.WriteEnd();
132 if (!is_motion_buffer_ready_
) {
133 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] = 1;
134 CheckMotionBufferReadyToRead();
138 bool DataFetcherImplAndroid::Start(EventType event_type
) {
139 DCHECK(!device_orientation_
.is_null());
140 return Java_DeviceMotionAndOrientation_start(
141 AttachCurrentThread(), device_orientation_
.obj(),
142 reinterpret_cast<intptr_t>(this), static_cast<jint
>(event_type
),
143 kInertialSensorIntervalMillis
);
146 void DataFetcherImplAndroid::Stop(EventType event_type
) {
147 DCHECK(!device_orientation_
.is_null());
148 Java_DeviceMotionAndOrientation_stop(
149 AttachCurrentThread(), device_orientation_
.obj(),
150 static_cast<jint
>(event_type
));
153 int DataFetcherImplAndroid::GetNumberActiveDeviceMotionSensors() {
154 DCHECK(!device_orientation_
.is_null());
155 return Java_DeviceMotionAndOrientation_getNumberActiveDeviceMotionSensors(
156 AttachCurrentThread(), device_orientation_
.obj());
160 // ----- Shared memory API methods
164 bool DataFetcherImplAndroid::StartFetchingDeviceMotionData(
165 DeviceMotionHardwareBuffer
* buffer
) {
168 base::AutoLock
autolock(motion_buffer_lock_
);
169 device_motion_buffer_
= buffer
;
170 ClearInternalMotionBuffers();
172 bool success
= Start(kTypeMotion
);
174 // If no motion data can ever be provided, the number of active device motion
175 // sensors will be zero. In that case flag the shared memory buffer
176 // as ready to read, as it will not change anyway.
177 number_active_device_motion_sensors_
= GetNumberActiveDeviceMotionSensors();
179 base::AutoLock
autolock(motion_buffer_lock_
);
180 CheckMotionBufferReadyToRead();
185 void DataFetcherImplAndroid::StopFetchingDeviceMotionData() {
188 base::AutoLock
autolock(motion_buffer_lock_
);
189 if (device_motion_buffer_
) {
190 ClearInternalMotionBuffers();
191 device_motion_buffer_
= NULL
;
196 void DataFetcherImplAndroid::CheckMotionBufferReadyToRead() {
197 if (received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] +
198 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
] +
199 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] ==
200 number_active_device_motion_sensors_
) {
201 device_motion_buffer_
->seqlock
.WriteBegin();
202 device_motion_buffer_
->data
.interval
= kInertialSensorIntervalMillis
;
203 device_motion_buffer_
->seqlock
.WriteEnd();
204 SetMotionBufferReadyStatus(true);
206 UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
207 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION
] > 0);
208 UMA_HISTOGRAM_BOOLEAN(
209 "InertialSensor.AccelerometerIncGravityAndroidAvailable",
210 received_motion_data_
[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY
]
212 UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
213 received_motion_data_
[RECEIVED_MOTION_DATA_ROTATION_RATE
] > 0);
217 void DataFetcherImplAndroid::SetMotionBufferReadyStatus(bool ready
) {
218 device_motion_buffer_
->seqlock
.WriteBegin();
219 device_motion_buffer_
->data
.allAvailableSensorsAreActive
= ready
;
220 device_motion_buffer_
->seqlock
.WriteEnd();
221 is_motion_buffer_ready_
= ready
;
224 void DataFetcherImplAndroid::ClearInternalMotionBuffers() {
225 memset(received_motion_data_
, 0, sizeof(received_motion_data_
));
226 number_active_device_motion_sensors_
= 0;
227 SetMotionBufferReadyStatus(false);
230 // --- Device Orientation
232 void DataFetcherImplAndroid::SetOrientationBufferReadyStatus(bool ready
) {
233 device_orientation_buffer_
->seqlock
.WriteBegin();
234 device_orientation_buffer_
->data
.absolute
= ready
;
235 device_orientation_buffer_
->data
.hasAbsolute
= ready
;
236 device_orientation_buffer_
->data
.allAvailableSensorsAreActive
= ready
;
237 device_orientation_buffer_
->seqlock
.WriteEnd();
238 is_orientation_buffer_ready_
= ready
;
241 bool DataFetcherImplAndroid::StartFetchingDeviceOrientationData(
242 DeviceOrientationHardwareBuffer
* buffer
) {
245 base::AutoLock
autolock(orientation_buffer_lock_
);
246 device_orientation_buffer_
= buffer
;
248 bool success
= Start(kTypeOrientation
);
251 base::AutoLock
autolock(orientation_buffer_lock_
);
252 // If Start() was unsuccessful then set the buffer ready flag to true
253 // to start firing all-null events.
254 SetOrientationBufferReadyStatus(!success
);
258 updateRotationVectorHistogram(false);
263 void DataFetcherImplAndroid::StopFetchingDeviceOrientationData() {
264 Stop(kTypeOrientation
);
266 base::AutoLock
autolock(orientation_buffer_lock_
);
267 if (device_orientation_buffer_
) {
268 SetOrientationBufferReadyStatus(false);
269 device_orientation_buffer_
= NULL
;
274 } // namespace content