Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / content / browser / device_orientation / sensor_manager_android.cc
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.
4
5 #include "content/browser/device_orientation/sensor_manager_android.h"
6
7 #include <string.h>
8
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"
14
15 using base::android::AttachCurrentThread;
16
17 namespace {
18
19 static void updateRotationVectorHistogram(bool value) {
20   UMA_HISTOGRAM_BOOLEAN("InertialSensor.RotationVectorAndroidAvailable", value);
21 }
22
23 }
24
25 namespace content {
26
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()));
38 }
39
40 SensorManagerAndroid::~SensorManagerAndroid() {
41 }
42
43 bool SensorManagerAndroid::Register(JNIEnv* env) {
44   return RegisterNativesImpl(env);
45 }
46
47 SensorManagerAndroid* SensorManagerAndroid::GetInstance() {
48   return Singleton<SensorManagerAndroid,
49                    LeakySingletonTraits<SensorManagerAndroid> >::get();
50 }
51
52 void SensorManagerAndroid::GotOrientation(
53     JNIEnv*, jobject, double alpha, double beta, double gamma) {
54   base::AutoLock autolock(orientation_buffer_lock_);
55
56   if (!device_orientation_buffer_)
57     return;
58
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();
67
68   if (!is_orientation_buffer_ready_) {
69     SetOrientationBufferReadyStatus(true);
70     updateRotationVectorHistogram(true);
71   }
72 }
73
74 void SensorManagerAndroid::GotAcceleration(
75     JNIEnv*, jobject, double x, double y, double z) {
76   base::AutoLock autolock(motion_buffer_lock_);
77
78   if (!device_motion_buffer_)
79     return;
80
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();
89
90   if (!is_motion_buffer_ready_) {
91     received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] = 1;
92     CheckMotionBufferReadyToRead();
93   }
94 }
95
96 void SensorManagerAndroid::GotAccelerationIncludingGravity(
97     JNIEnv*, jobject, double x, double y, double z) {
98   base::AutoLock autolock(motion_buffer_lock_);
99
100   if (!device_motion_buffer_)
101     return;
102
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();
111
112   if (!is_motion_buffer_ready_) {
113     received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] = 1;
114     CheckMotionBufferReadyToRead();
115   }
116 }
117
118 void SensorManagerAndroid::GotRotationRate(
119     JNIEnv*, jobject, double alpha, double beta, double gamma) {
120   base::AutoLock autolock(motion_buffer_lock_);
121
122   if (!device_motion_buffer_)
123     return;
124
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();
133
134   if (!is_motion_buffer_ready_) {
135     received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] = 1;
136     CheckMotionBufferReadyToRead();
137   }
138 }
139
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);
146 }
147
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));
153 }
154
155 int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
156   DCHECK(!device_orientation_.is_null());
157   return Java_DeviceMotionAndOrientation_getNumberActiveDeviceMotionSensors(
158       AttachCurrentThread(), device_orientation_.obj());
159 }
160
161
162 // ----- Shared memory API methods
163
164 // --- Device Motion
165
166 bool SensorManagerAndroid::StartFetchingDeviceMotionData(
167     DeviceMotionHardwareBuffer* buffer) {
168   DCHECK(buffer);
169   {
170     base::AutoLock autolock(motion_buffer_lock_);
171     device_motion_buffer_ = buffer;
172     ClearInternalMotionBuffers();
173   }
174   bool success = Start(kTypeMotion);
175
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();
180   {
181     base::AutoLock autolock(motion_buffer_lock_);
182     CheckMotionBufferReadyToRead();
183   }
184   return success;
185 }
186
187 void SensorManagerAndroid::StopFetchingDeviceMotionData() {
188   Stop(kTypeMotion);
189   {
190     base::AutoLock autolock(motion_buffer_lock_);
191     if (device_motion_buffer_) {
192       ClearInternalMotionBuffers();
193       device_motion_buffer_ = NULL;
194     }
195   }
196 }
197
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);
207
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]
213         > 0);
214     UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
215         received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
216   }
217 }
218
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;
224 }
225
226 void SensorManagerAndroid::ClearInternalMotionBuffers() {
227   memset(received_motion_data_, 0, sizeof(received_motion_data_));
228   number_active_device_motion_sensors_ = 0;
229   SetMotionBufferReadyStatus(false);
230 }
231
232 // --- Device Orientation
233
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;
241 }
242
243 bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
244     DeviceOrientationHardwareBuffer* buffer) {
245   DCHECK(buffer);
246   {
247     base::AutoLock autolock(orientation_buffer_lock_);
248     device_orientation_buffer_ = buffer;
249   }
250   bool success = Start(kTypeOrientation);
251
252   {
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);
257   }
258
259   if (!success)
260     updateRotationVectorHistogram(false);
261
262   return success;
263 }
264
265 void SensorManagerAndroid::StopFetchingDeviceOrientationData() {
266   Stop(kTypeOrientation);
267   {
268     base::AutoLock autolock(orientation_buffer_lock_);
269     if (device_orientation_buffer_) {
270       SetOrientationBufferReadyStatus(false);
271       device_orientation_buffer_ = NULL;
272     }
273   }
274 }
275
276 }  // namespace content