Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java

Issue 12771008: Implement java-side browser sensor polling for device motion and device orientation DOM events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java b/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
similarity index 44%
rename from content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java
rename to content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
index a77cd28b27ab6901f6a12f7a2e4e012b3e7c8f71..31eaadb40305bb4f7fdb99fde9c565dff3286cb1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -12,17 +12,23 @@ import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Looper;
+import com.google.common.collect.ImmutableMap;
Peter Beverloo 2013/03/13 14:02:47 This is now unused.
timvolodine 2013/03/13 15:29:49 Done.
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.WeakContext;
import java.util.List;
+import java.util.Map;
Peter Beverloo 2013/03/13 14:02:47 This is now unused.
timvolodine 2013/03/13 15:29:49 Done.
+import java.util.Set;
/**
- * Android implementation of the DeviceOrientation API.
+ * Android implementation of the device motion and orientation APIs.
*/
@JNINamespace("content")
-class DeviceOrientation implements SensorEventListener {
+class DeviceMotionAndOrientation implements SensorEventListener {
// These fields are lazily initialized by getHandler().
private Thread mThread;
@@ -44,14 +50,40 @@ class DeviceOrientation implements SensorEventListener {
// The geomagnetic vector expressed in the body frame.
private float[] mMagneticFieldVector;
+ // The linear acceleration vector expressed in the body frame.
+ private float[] mAccelerationVector;
Peter Beverloo 2013/03/13 14:02:47 Should we perhaps use this member instead of mGrav
timvolodine 2013/03/13 15:29:49 Done.
+
+ // The angular speed at which the device is rotating around the body frame.
+ private float[] mGyroscopeVector;
Peter Beverloo 2013/03/13 14:02:47 We don't need this member.
timvolodine 2013/03/13 15:29:49 Done.
+
// Lazily initialized when registering for notifications.
private SensorManager mSensorManager;
// The only instance of that class and its associated lock.
- private static DeviceOrientation sSingleton;
+ private static DeviceMotionAndOrientation sSingleton;
private static Object sSingletonLock = new Object();
- private DeviceOrientation() {
+ /**
+ * constants for using in JNI calls, also see
+ * content/browser/device_orientation/data_fetcher_impl_android.cc
+ */
+ private static final int DEVICE_ORIENTATION = 0;
+ private static final int DEVICE_MOTION = 1;
+
+ private static ImmutableSet<Integer> DEVICE_ORIENTATION_SENSORS = ImmutableSet.of(
+ Sensor.TYPE_ACCELEROMETER,
+ Sensor.TYPE_MAGNETIC_FIELD);
+
+ private static ImmutableSet<Integer> DEVICE_MOTION_SENSORS = ImmutableSet.of(
+ Sensor.TYPE_ACCELEROMETER,
+ Sensor.TYPE_LINEAR_ACCELERATION,
+ Sensor.TYPE_GYROSCOPE);
+
+ private Set<Integer> mActiveSensors = Sets.newHashSet();
+ private boolean mDeviceMotionIsActive = false;
+ private boolean mDeviceOrientationIsActive = false;
+
+ private DeviceMotionAndOrientation() {
}
/**
@@ -61,33 +93,69 @@ class DeviceOrientation implements SensorEventListener {
* @param nativePtr Value to pass to nativeGotOrientation() for each event.
* @param rateInMilliseconds Requested callback rate in milliseconds. The
* actual rate may be higher. Unwanted events should be ignored.
+ * @param eventType type of event to listen to, can be either 0 for device
Miguel Garcia 2013/03/13 13:37:09 can you refer to the constants you created instead
Peter Beverloo 2013/03/13 14:02:47 s/type/Type/. Sentences begin with a capital.
timvolodine 2013/03/13 15:29:49 Done.
timvolodine 2013/03/13 15:29:49 Done.
+ * orientation, or 1 for device motion.
* @return True on success.
*/
@CalledByNative
- public boolean start(int nativePtr, int rateInMilliseconds) {
+ public boolean start(int nativePtr, int eventType, int rateInMilliseconds) {
+ boolean success = false;
+ Set<Integer> sensorsToActivate;
synchronized (mNativePtrLock) {
- stop();
- if (registerForSensors(rateInMilliseconds)) {
+ switch (eventType) {
+ case DEVICE_ORIENTATION:
+ sensorsToActivate = Sets.newHashSet(DEVICE_ORIENTATION_SENSORS);
+ sensorsToActivate.removeAll(mActiveSensors);
Miguel Garcia 2013/03/13 13:37:09 Since registerForSensors already filters out activ
Peter Beverloo 2013/03/13 14:02:47 +1. Dito on line 113.
timvolodine 2013/03/13 15:29:49 I've changed the registerForSensors method a bit,
timvolodine 2013/03/13 15:29:49 Done.
+ success = registerForSensors(sensorsToActivate, rateInMilliseconds, true);
+ break;
+ case DEVICE_MOTION:
+ Set<Integer> sensorsToActivate = Sets.newHashSet(DEVICE_MOTION_SENSORS);
+ sensorsToActivate.removeAll(mActiveSensors);
+ success = registerForSensors(sensorsToActivate, rateInMilliseconds, false);
Miguel Garcia 2013/03/13 13:37:09 can you explain why we allow missing sensors on mo
Peter Beverloo 2013/03/13 14:02:47 The specification doesn't mandate that either sens
timvolodine 2013/03/13 15:29:49 as Peter said, it's the spec On 2013/03/13 13:37:0
timvolodine 2013/03/13 15:29:49 Done.
Miguel Garcia 2013/03/13 16:04:29 Yeas I know I meant adding a comment explaining ex
timvolodine 2013/03/13 17:53:01 Done.
+ break;
+ default:
+ return false;
Peter Beverloo 2013/03/13 14:02:47 Can we assert here as this shouldn't happen?
timvolodine 2013/03/13 15:29:49 Done.
+ }
+ if (success) {
mNativePtr = nativePtr;
- return true;
+ setActiveEventType(eventType, true);
}
- return false;
+ return success;
}
}
/**
- * Stop listening for sensor events. Always succeeds.
+ * Stop listening for particular sensor events. Always succeeds.
Miguel Garcia 2013/03/13 16:04:29 I think you need to upgrade this java doc. Somethi
timvolodine 2013/03/13 17:53:01 Done.
*
+ * @param eventType type of event to listen to, can be either 0 for device
Peter Beverloo 2013/03/13 14:02:47 s/type/Type/.
timvolodine 2013/03/13 15:29:49 Done.
+ * orientation, or 1 for device motion.
* We strictly guarantee that nativeGotOrientation() will not be called
Miguel Garcia 2013/03/13 13:37:09 how about the other nativeGot* methods?
timvolodine 2013/03/13 15:29:49 Done.
* after this method returns.
*/
@CalledByNative
- public void stop() {
+ public void stop(int eventType) {
+ Set<Integer> sensorsToRemainActive = Sets.newHashSet();
synchronized (mNativePtrLock) {
- if (mNativePtr != 0) {
- mNativePtr = 0;
- unregisterForSensors();
+ switch (eventType) {
+ case DEVICE_ORIENTATION:
+ if (mDeviceMotionIsActive) {
+ sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
+ }
+ break;
+ case DEVICE_MOTION:
+ if (mDeviceOrientationIsActive) {
+ sensorsToRemainActive.addAll(DEVICE_ORIENTATION_SENSORS);
+ }
+ break;
+ default:
+ return;
Peter Beverloo 2013/03/13 14:02:47 Dito: Can we assert here as well?
timvolodine 2013/03/13 15:29:49 Done.
}
+
+ Set<Integer> sensorsToDeactivate = Sets.newHashSet(mActiveSensors);
+ sensorsToDeactivate.removeAll(sensorsToRemainActive);
+ unregisterForSensors(sensorsToDeactivate);
Miguel Garcia 2013/03/13 13:37:09 I don't understand all these set operations can't
timvolodine 2013/03/13 15:29:49 the set of sensors for both events overlaps, so we
Miguel Garcia 2013/03/13 16:04:29 Would it feel more natural to have 3 sets? common_
timvolodine 2013/03/13 17:53:01 that'll probably work too, but not sure if it woul
+ mNativePtr = 0;
+ setActiveEventType(eventType, false);
}
}
@@ -104,8 +172,24 @@ class DeviceOrientation implements SensorEventListener {
mGravityVector = new float[3];
}
System.arraycopy(event.values, 0, mGravityVector, 0, mGravityVector.length);
+ if (mDeviceMotionIsActive) {
Miguel Garcia 2013/03/13 13:37:09 why don't you use the same pattern than before, yo
Peter Beverloo 2013/03/13 14:02:47 I think this is the right approach. We don't need
timvolodine 2013/03/13 15:29:49 Done.
timvolodine 2013/03/13 15:29:49 agree with Peter's comment, we don't need to compu
Miguel Garcia 2013/03/13 16:04:29 ok On 2013/03/13 15:29:49, timvolodine wrote:
timvolodine 2013/03/13 17:53:01 Done.
+ gotAccelerationIncludingGravity(mGravityVector[0], mGravityVector[1],
+ mGravityVector[2]);
+ }
+ break;
+ case Sensor.TYPE_LINEAR_ACCELERATION:
+ if (mAccelerationVector == null) {
+ mAccelerationVector = new float[3];
+ }
+ gotAcceleration(mAccelerationVector[0], mAccelerationVector[1],
+ mAccelerationVector[2]);
Peter Beverloo 2013/03/13 14:02:47 What fills mAccelerationVector? :-). This should
timvolodine 2013/03/13 15:29:49 Done.
+ break;
+ case Sensor.TYPE_GYROSCOPE:
+ if (mGyroscopeVector == null) {
+ mGyroscopeVector = new float[3];
+ }
+ gotRotationRate(mGyroscopeVector[0], mGyroscopeVector[1], mGyroscopeVector[2]);
Peter Beverloo 2013/03/13 14:02:47 Dito to line 184.
timvolodine 2013/03/13 15:29:49 Done.
break;
-
case Sensor.TYPE_MAGNETIC_FIELD:
if (mMagneticFieldVector == null) {
mMagneticFieldVector = new float[3];
@@ -113,16 +197,17 @@ class DeviceOrientation implements SensorEventListener {
System.arraycopy(event.values, 0, mMagneticFieldVector, 0,
mMagneticFieldVector.length);
break;
-
default:
// Unexpected
return;
}
- getOrientationUsingGetRotationMatrix();
+ if (mDeviceOrientationIsActive) {
+ getOrientationUsingGetRotationMatrix();
+ }
}
- void getOrientationUsingGetRotationMatrix() {
+ private void getOrientationUsingGetRotationMatrix() {
if (mGravityVector == null || mMagneticFieldVector == null) {
return;
}
@@ -163,15 +248,6 @@ class DeviceOrientation implements SensorEventListener {
gotOrientation(alpha, beta, gamma);
}
- boolean registerForSensors(int rateInMilliseconds) {
- if (registerForSensorType(Sensor.TYPE_ACCELEROMETER, rateInMilliseconds)
- && registerForSensorType(Sensor.TYPE_MAGNETIC_FIELD, rateInMilliseconds)) {
- return true;
- }
- unregisterForSensors();
- return false;
- }
-
private SensorManager getSensorManager() {
if (mSensorManager != null) {
return mSensorManager;
@@ -180,12 +256,50 @@ class DeviceOrientation implements SensorEventListener {
return mSensorManager;
}
- void unregisterForSensors() {
- SensorManager sensorManager = getSensorManager();
- if (sensorManager == null) {
- return;
+ private void setActiveEventType(int eventType, boolean value) {
+ switch (eventType) {
+ case DEVICE_ORIENTATION:
+ mDeviceOrientationIsActive = value;
+ return;
+ case DEVICE_MOTION:
+ mDeviceMotionIsActive = value;
+ return;
+ }
+ }
+
+ /**
+ * @param sensorTypes List of sensors to activate.
+ * @param rateInMilliseconds intented delay (in ms) between sensor readings.
Peter Beverloo 2013/03/13 14:02:47 s/intented/Intended/. Can you spell out ms? Idea
timvolodine 2013/03/13 15:29:49 Done.
+ * @param failOnMissingSensor If true the method returns true only if all sensors could be
+ * activated. When false the method return true if at least one
+ * sensor in sensorTypes could be activated.
+ */
+ private boolean registerForSensors(Iterable<Integer> sensorTypes, int rateInMilliseconds,
Miguel Garcia 2013/03/13 13:37:09 can this be called registerSensors while you are a
timvolodine 2013/03/13 15:29:49 Done.
+ boolean failOnMissingSensor) {
+ boolean success = false;
+ for (Integer sensorType : sensorTypes) {
+ if (!mActiveSensors.contains(sensorType)) {
+ boolean result = registerForSensorType(sensorType, rateInMilliseconds);
+ success |= result;
+ if (!result && failOnMissingSensor) {
+ // restore the previous state upon failure
+ unregisterForSensors(sensorTypes);
+ return false;
+ }
+ }
+ mActiveSensors.add(sensorType);
Miguel Garcia 2013/03/13 13:37:09 should'nt you be checkout if the sensor activation
timvolodine 2013/03/13 15:29:49 right Done. On 2013/03/13 13:37:09, Miguel Garcia
+ }
+ return success;
+ }
+
+ private void unregisterForSensors(Iterable<Integer> sensorTypes) {
+ for (Integer sensorType : sensorTypes) {
+ if (mActiveSensors.contains(sensorType)) {
+ getSensorManager().unregisterListener(this,
+ getSensorManager().getDefaultSensor(sensorType));
+ mActiveSensors.remove(sensorType);
+ }
}
- sensorManager.unregisterListener(this);
}
boolean registerForSensorType(int type, int rateInMilliseconds) {
@@ -193,20 +307,17 @@ class DeviceOrientation implements SensorEventListener {
if (sensorManager == null) {
return false;
}
- List<Sensor> sensors = sensorManager.getSensorList(type);
- if (sensors.isEmpty()) {
+ Sensor defaultSensor = sensorManager.getDefaultSensor(type);
Peter Beverloo 2013/03/13 14:02:47 Please see my replies in regards to this on the ol
timvolodine 2013/03/13 15:29:49 Done.
+ if (defaultSensor == null) {
return false;
}
final int rateInMicroseconds = 1000 * rateInMilliseconds;
- // We want to err on the side of getting more events than we need.
- final int requestedRate = rateInMicroseconds / 2;
-
- // TODO(steveblock): Consider handling multiple sensors.
- return sensorManager.registerListener(this, sensors.get(0), requestedRate, getHandler());
+ return sensorManager.registerListener(this, defaultSensor, rateInMicroseconds,
+ getHandler());
}
- void gotOrientation(double alpha, double beta, double gamma) {
+ private void gotOrientation(double alpha, double beta, double gamma) {
synchronized (mNativePtrLock) {
if (mNativePtr != 0) {
nativeGotOrientation(mNativePtr, alpha, beta, gamma);
@@ -214,6 +325,30 @@ class DeviceOrientation implements SensorEventListener {
}
}
+ private void gotAcceleration(double x, double y, double z) {
+ synchronized (mNativePtrLock) {
+ if (mNativePtr != 0) {
+ nativeGotAcceleration(mNativePtr, x, y, z);
+ }
+ }
+ }
+
+ private void gotAccelerationIncludingGravity(double x, double y, double z) {
+ synchronized (mNativePtrLock) {
+ if (mNativePtr != 0) {
+ nativeGotAccelerationIncludingGravity(mNativePtr, x, y, z);
+ }
+ }
+ }
+
+ private void gotRotationRate(double alpha, double beta, double gamma) {
+ synchronized (mNativePtrLock) {
+ if (mNativePtr != 0) {
+ nativeGotRotationRate(mNativePtr, alpha, beta, gamma);
+ }
+ }
+ }
+
private Handler getHandler() {
synchronized (mHandlerLock) {
// If we don't have a background thread, start it now.
@@ -251,19 +386,46 @@ class DeviceOrientation implements SensorEventListener {
}
@CalledByNative
- private static DeviceOrientation getInstance() {
+ private static DeviceMotionAndOrientation getInstance() {
synchronized (sSingletonLock) {
if (sSingleton == null) {
- sSingleton = new DeviceOrientation();
+ sSingleton = new DeviceMotionAndOrientation();
}
return sSingleton;
}
}
/**
- * See chrome/browser/device_orientation/data_fetcher_impl_android.cc
+ * Native JNI calls,
+ * see content/browser/device_orientation/data_fetcher_impl_android.cc
+ */
+
+ /**
+ * Orientation of the device with respect to its reference frame.
*/
private native void nativeGotOrientation(
int nativeDataFetcherImplAndroid,
double alpha, double beta, double gamma);
-}
+
+ /**
+ * Linear acceleration without gravity of the device with respect to its body frame.
+ */
+ private native void nativeGotAcceleration(
+ int nativeDataFetcherImplAndroid,
+ double x, double y, double z);
+
+ /**
+ * Acceleration including gravity of the device with respect to its body frame.
+ */
+ private native void nativeGotAccelerationIncludingGravity(
+ int nativeDataFetcherImplAndroid,
+ double x, double y, double z);
+
+ /**
+ * Rotation rate of the device with respect to its body frame.
+ */
+ private native void nativeGotRotationRate(
+ int nativeDataFetcherImplAndroid,
+ double alpha, double beta, double gamma);
+
+}
« no previous file with comments | « content/content_jni.gypi ('k') | content/public/android/java/src/org/chromium/content/browser/DeviceOrientation.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698