| Index: content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java b/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
|
| deleted file mode 100644
|
| index e2e91f380f6d89a85484700bdceefc666fca27ab..0000000000000000000000000000000000000000
|
| --- a/content/public/android/java/src/org/chromium/content/browser/DeviceSensors.java
|
| +++ /dev/null
|
| @@ -1,703 +0,0 @@
|
| -// Copyright 2014 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.
|
| -
|
| -package org.chromium.content.browser;
|
| -
|
| -import android.content.Context;
|
| -import android.hardware.Sensor;
|
| -import android.hardware.SensorEvent;
|
| -import android.hardware.SensorEventListener;
|
| -import android.hardware.SensorManager;
|
| -import android.os.Handler;
|
| -import android.os.HandlerThread;
|
| -
|
| -import org.chromium.base.CollectionUtil;
|
| -import org.chromium.base.Log;
|
| -import org.chromium.base.ThreadUtils;
|
| -import org.chromium.base.VisibleForTesting;
|
| -import org.chromium.base.annotations.CalledByNative;
|
| -import org.chromium.base.annotations.JNINamespace;
|
| -
|
| -import java.util.HashSet;
|
| -import java.util.List;
|
| -import java.util.Set;
|
| -
|
| -/**
|
| - * Android implementation of the device {motion|orientation|light} APIs.
|
| - */
|
| -@JNINamespace("content")
|
| -class DeviceSensors implements SensorEventListener {
|
| -
|
| - private static final String TAG = "cr.DeviceSensors";
|
| -
|
| - // Matches kEnableExperimentalWebPlatformFeatures.
|
| - private static final String EXPERIMENTAL_WEB_PLAFTORM_FEATURES =
|
| - "enable-experimental-web-platform-features";
|
| -
|
| - // These fields are lazily initialized by getHandler().
|
| - private Thread mThread;
|
| - private Handler mHandler;
|
| -
|
| - // A reference to the application context in order to acquire the SensorService.
|
| - private final Context mAppContext;
|
| -
|
| - // The lock to access the mHandler.
|
| - private final Object mHandlerLock = new Object();
|
| -
|
| - // Non-zero if and only if we're listening for events.
|
| - // To avoid race conditions on the C++ side, access must be synchronized.
|
| - private long mNativePtr;
|
| -
|
| - // The lock to access the mNativePtr.
|
| - private final Object mNativePtrLock = new Object();
|
| -
|
| - // The geomagnetic vector expressed in the body frame.
|
| - private float[] mMagneticFieldVector;
|
| -
|
| - // Holds a shortened version of the rotation vector for compatibility purposes.
|
| - private float[] mTruncatedRotationVector;
|
| -
|
| - // Holds current rotation matrix for the device.
|
| - private float[] mDeviceRotationMatrix;
|
| -
|
| - // Holds Euler angles corresponding to the rotation matrix.
|
| - private double[] mRotationAngles;
|
| -
|
| - // Lazily initialized when registering for notifications.
|
| - private SensorManagerProxy mSensorManagerProxy;
|
| -
|
| - // The only instance of that class and its associated lock.
|
| - private static DeviceSensors sSingleton;
|
| - private static Object sSingletonLock = new Object();
|
| -
|
| - static final Set<Integer> DEVICE_ORIENTATION_SENSORS_A = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_GAME_ROTATION_VECTOR);
|
| - static final Set<Integer> DEVICE_ORIENTATION_SENSORS_B = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_ROTATION_VECTOR);
|
| - // Option C backup sensors are used when options A and B are not available.
|
| - static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_ACCELEROMETER,
|
| - Sensor.TYPE_MAGNETIC_FIELD);
|
| - static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_ROTATION_VECTOR);
|
| - static final Set<Integer> DEVICE_MOTION_SENSORS = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_ACCELEROMETER,
|
| - Sensor.TYPE_LINEAR_ACCELERATION,
|
| - Sensor.TYPE_GYROSCOPE);
|
| - static final Set<Integer> DEVICE_LIGHT_SENSORS = CollectionUtil.newHashSet(
|
| - Sensor.TYPE_LIGHT);
|
| -
|
| - @VisibleForTesting
|
| - final Set<Integer> mActiveSensors = new HashSet<Integer>();
|
| - final List<Set<Integer>> mOrientationSensorSets;
|
| - Set<Integer> mDeviceOrientationSensors;
|
| - boolean mDeviceLightIsActive;
|
| - boolean mDeviceMotionIsActive;
|
| - boolean mDeviceOrientationIsActive;
|
| - boolean mDeviceOrientationIsActiveWithBackupSensors;
|
| - boolean mDeviceOrientationAbsoluteIsActive;
|
| - boolean mOrientationNotAvailable;
|
| -
|
| - protected DeviceSensors(Context context) {
|
| - mAppContext = context.getApplicationContext();
|
| -
|
| - mOrientationSensorSets = CollectionUtil.newArrayList(DEVICE_ORIENTATION_SENSORS_A,
|
| - DEVICE_ORIENTATION_SENSORS_B,
|
| - DEVICE_ORIENTATION_SENSORS_C);
|
| - }
|
| -
|
| - // For orientation we use a 3-way fallback approach where up to 3 different sets of sensors
|
| - // are attempted if necessary. The sensors to be used for orientation are determined in the
|
| - // following order:
|
| - // A: GAME_ROTATION_VECTOR (relative)
|
| - // B: ROTATION_VECTOR (absolute)
|
| - // C: combination of ACCELEROMETER and MAGNETIC_FIELD (absolute)
|
| - // Some of the sensors may not be available depending on the device and Android version, so
|
| - // the 3-way fallback ensures selection of the best possible option.
|
| - // Examples:
|
| - // * Nexus 9, Android 5.0.2 --> option A
|
| - // * Nexus 10, Android 5.1 --> option B
|
| - // * Moto G, Android 4.4.4 --> option C
|
| - @VisibleForTesting
|
| - protected boolean registerOrientationSensorsWithFallback(int rateInMicroseconds) {
|
| - if (mOrientationNotAvailable) return false;
|
| - if (mDeviceOrientationSensors != null) {
|
| - return registerSensors(mDeviceOrientationSensors, rateInMicroseconds, true);
|
| - }
|
| - ensureRotationStructuresAllocated();
|
| -
|
| - for (Set<Integer> sensors : mOrientationSensorSets) {
|
| - mDeviceOrientationSensors = sensors;
|
| - if (registerSensors(mDeviceOrientationSensors, rateInMicroseconds, true)) return true;
|
| - }
|
| -
|
| - mOrientationNotAvailable = true;
|
| - mDeviceOrientationSensors = null;
|
| - mDeviceRotationMatrix = null;
|
| - mRotationAngles = null;
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Start listening for sensor events. If this object is already listening
|
| - * for events, the old callback is unregistered first.
|
| - *
|
| - * @param nativePtr Value to pass to nativeGotOrientation() for each event.
|
| - * @param rateInMicroseconds Requested callback rate in microseconds. The
|
| - * actual rate may be higher. Unwanted events should be ignored.
|
| - * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION,
|
| - * DEVICE_ORIENTATION_ABSOLUTE, DEVICE_MOTION or DEVICE_LIGHT.
|
| - * @return True on success.
|
| - */
|
| - @CalledByNative
|
| - public boolean start(long nativePtr, int eventType, int rateInMicroseconds) {
|
| - boolean success = false;
|
| - synchronized (mNativePtrLock) {
|
| - switch (eventType) {
|
| - case ConsumerType.ORIENTATION:
|
| - success = registerOrientationSensorsWithFallback(rateInMicroseconds);
|
| - break;
|
| - case ConsumerType.ORIENTATION_ABSOLUTE:
|
| - ensureRotationStructuresAllocated();
|
| - success = registerSensors(DEVICE_ORIENTATION_ABSOLUTE_SENSORS,
|
| - rateInMicroseconds, true);
|
| - break;
|
| - case ConsumerType.MOTION:
|
| - // note: device motion spec does not require all sensors to be available
|
| - success = registerSensors(DEVICE_MOTION_SENSORS, rateInMicroseconds, false);
|
| - break;
|
| - case ConsumerType.LIGHT:
|
| - success = registerSensors(DEVICE_LIGHT_SENSORS, rateInMicroseconds, true);
|
| - break;
|
| - default:
|
| - Log.e(TAG, "Unknown event type: %d", eventType);
|
| - return false;
|
| - }
|
| - if (success) {
|
| - mNativePtr = nativePtr;
|
| - setEventTypeActive(eventType, true);
|
| - }
|
| - return success;
|
| - }
|
| - }
|
| -
|
| - @CalledByNative
|
| - public int getNumberActiveDeviceMotionSensors() {
|
| - Set<Integer> deviceMotionSensors = new HashSet<Integer>(DEVICE_MOTION_SENSORS);
|
| - deviceMotionSensors.removeAll(mActiveSensors);
|
| - return DEVICE_MOTION_SENSORS.size() - deviceMotionSensors.size();
|
| - }
|
| -
|
| - @CalledByNative
|
| - public int getOrientationSensorTypeUsed() {
|
| - if (mOrientationNotAvailable) {
|
| - return OrientationSensorType.NOT_AVAILABLE;
|
| - }
|
| - if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_A) {
|
| - return OrientationSensorType.GAME_ROTATION_VECTOR;
|
| - }
|
| - if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) {
|
| - return OrientationSensorType.ROTATION_VECTOR;
|
| - }
|
| - if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C) {
|
| - return OrientationSensorType.ACCELEROMETER_MAGNETIC;
|
| - }
|
| -
|
| - assert false; // should never happen
|
| - return OrientationSensorType.NOT_AVAILABLE;
|
| - }
|
| -
|
| - /**
|
| - * Stop listening to sensors for a given event type. Ensures that sensors are not disabled
|
| - * if they are still in use by a different event type.
|
| - *
|
| - * @param eventType Type of event to listen to, can be either DEVICE_ORIENTATION or
|
| - * DEVICE_MOTION or DEVICE_LIGHT.
|
| - * We strictly guarantee that the corresponding native*() methods will not be called
|
| - * after this method returns.
|
| - */
|
| - @CalledByNative
|
| - public void stop(int eventType) {
|
| - Set<Integer> sensorsToRemainActive = new HashSet<Integer>();
|
| -
|
| - synchronized (mNativePtrLock) {
|
| - if (mDeviceOrientationIsActive && eventType != ConsumerType.ORIENTATION) {
|
| - sensorsToRemainActive.addAll(mDeviceOrientationSensors);
|
| - }
|
| -
|
| - if (mDeviceOrientationAbsoluteIsActive
|
| - && eventType != ConsumerType.ORIENTATION_ABSOLUTE) {
|
| - sensorsToRemainActive.addAll(DEVICE_ORIENTATION_ABSOLUTE_SENSORS);
|
| - }
|
| -
|
| - if (mDeviceMotionIsActive && eventType != ConsumerType.MOTION) {
|
| - sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS);
|
| - }
|
| -
|
| - if (mDeviceLightIsActive && eventType != ConsumerType.LIGHT) {
|
| - sensorsToRemainActive.addAll(DEVICE_LIGHT_SENSORS);
|
| - }
|
| -
|
| - Set<Integer> sensorsToDeactivate = new HashSet<Integer>(mActiveSensors);
|
| - sensorsToDeactivate.removeAll(sensorsToRemainActive);
|
| - unregisterSensors(sensorsToDeactivate);
|
| - setEventTypeActive(eventType, false);
|
| - if (mActiveSensors.isEmpty()) {
|
| - mNativePtr = 0;
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
| - // Nothing
|
| - }
|
| -
|
| - @Override
|
| - public void onSensorChanged(SensorEvent event) {
|
| - sensorChanged(event.sensor.getType(), event.values);
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - void sensorChanged(int type, float[] values) {
|
| - switch (type) {
|
| - case Sensor.TYPE_ACCELEROMETER:
|
| - if (mDeviceMotionIsActive) {
|
| - gotAccelerationIncludingGravity(values[0], values[1], values[2]);
|
| - }
|
| - if (mDeviceOrientationIsActiveWithBackupSensors) {
|
| - getOrientationFromGeomagneticVectors(values, mMagneticFieldVector);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_LINEAR_ACCELERATION:
|
| - if (mDeviceMotionIsActive) {
|
| - gotAcceleration(values[0], values[1], values[2]);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_GYROSCOPE:
|
| - if (mDeviceMotionIsActive) {
|
| - gotRotationRate(values[0], values[1], values[2]);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_ROTATION_VECTOR:
|
| - if (mDeviceOrientationAbsoluteIsActive) {
|
| - convertRotationVectorToAngles(values, mRotationAngles);
|
| - gotOrientationAbsolute(mRotationAngles[0], mRotationAngles[1],
|
| - mRotationAngles[2]);
|
| - }
|
| - if (mDeviceOrientationIsActive
|
| - && mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) {
|
| - if (!mDeviceOrientationAbsoluteIsActive) {
|
| - // only compute if not already computed for absolute orientation above.
|
| - convertRotationVectorToAngles(values, mRotationAngles);
|
| - }
|
| - gotOrientation(mRotationAngles[0], mRotationAngles[1], mRotationAngles[2]);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_GAME_ROTATION_VECTOR:
|
| - if (mDeviceOrientationIsActive) {
|
| - convertRotationVectorToAngles(values, mRotationAngles);
|
| - gotOrientation(mRotationAngles[0], mRotationAngles[1], mRotationAngles[2]);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_MAGNETIC_FIELD:
|
| - if (mDeviceOrientationIsActiveWithBackupSensors) {
|
| - if (mMagneticFieldVector == null) {
|
| - mMagneticFieldVector = new float[3];
|
| - }
|
| - System.arraycopy(values, 0, mMagneticFieldVector, 0,
|
| - mMagneticFieldVector.length);
|
| - }
|
| - break;
|
| - case Sensor.TYPE_LIGHT:
|
| - if (mDeviceLightIsActive) {
|
| - gotLight(values[0]);
|
| - }
|
| - break;
|
| - default:
|
| - // Unexpected
|
| - return;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns orientation angles from a rotation matrix, such that the angles are according
|
| - * to spec {@link http://dev.w3.org/geo/api/spec-source-orientation.html}.
|
| - * <p>
|
| - * It is assumed the rotation matrix transforms a 3D column vector from device coordinate system
|
| - * to the world's coordinate system, as e.g. computed by {@see SensorManager.getRotationMatrix}.
|
| - * <p>
|
| - * In particular we compute the decomposition of a given rotation matrix R such that <br>
|
| - * R = Rz(alpha) * Rx(beta) * Ry(gamma), <br>
|
| - * where Rz, Rx and Ry are rotation matrices around Z, X and Y axes in the world coordinate
|
| - * reference frame respectively. The reference frame consists of three orthogonal axes X, Y, Z
|
| - * where X points East, Y points north and Z points upwards perpendicular to the ground plane.
|
| - * The computed angles alpha, beta and gamma are in radians and clockwise-positive when viewed
|
| - * along the positive direction of the corresponding axis. Except for the special case when the
|
| - * beta angle is +-pi/2 these angles uniquely define the orientation of a mobile device in 3D
|
| - * space. The alpha-beta-gamma representation resembles the yaw-pitch-roll convention used in
|
| - * vehicle dynamics, however it does not exactly match it. One of the differences is that the
|
| - * 'pitch' angle beta is allowed to be within [-pi, pi). A mobile device with pitch angle
|
| - * greater than pi/2 could correspond to a user lying down and looking upward at the screen.
|
| - *
|
| - * <p>
|
| - * Upon return the array values is filled with the result,
|
| - * <ul>
|
| - * <li>values[0]: rotation around the Z axis, alpha in [0, 2*pi)</li>
|
| - * <li>values[1]: rotation around the X axis, beta in [-pi, pi)</li>
|
| - * <li>values[2]: rotation around the Y axis, gamma in [-pi/2, pi/2)</li>
|
| - * </ul>
|
| - * <p>
|
| - *
|
| - * @param matrixR
|
| - * a 3x3 rotation matrix {@see SensorManager.getRotationMatrix}.
|
| - *
|
| - * @param values
|
| - * an array of 3 doubles to hold the result.
|
| - *
|
| - * @return the array values passed as argument.
|
| - */
|
| - @VisibleForTesting
|
| - public static double[] computeDeviceOrientationFromRotationMatrix(
|
| - float[] matrixR, double[] values) {
|
| - /*
|
| - * 3x3 (length=9) case:
|
| - * / R[ 0] R[ 1] R[ 2] \
|
| - * | R[ 3] R[ 4] R[ 5] |
|
| - * \ R[ 6] R[ 7] R[ 8] /
|
| - *
|
| - */
|
| - if (matrixR.length != 9) return values;
|
| -
|
| - if (matrixR[8] > 0) { // cos(beta) > 0
|
| - values[0] = Math.atan2(-matrixR[1], matrixR[4]);
|
| - values[1] = Math.asin(matrixR[7]); // beta (-pi/2, pi/2)
|
| - values[2] = Math.atan2(-matrixR[6], matrixR[8]); // gamma (-pi/2, pi/2)
|
| - } else if (matrixR[8] < 0) { // cos(beta) < 0
|
| - values[0] = Math.atan2(matrixR[1], -matrixR[4]);
|
| - values[1] = -Math.asin(matrixR[7]);
|
| - values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi,-pi/2) U (pi/2,pi)
|
| - values[2] = Math.atan2(matrixR[6], -matrixR[8]); // gamma (-pi/2, pi/2)
|
| - } else { // R[8] == 0
|
| - if (matrixR[6] > 0) { // cos(gamma) == 0, cos(beta) > 0
|
| - values[0] = Math.atan2(-matrixR[1], matrixR[4]);
|
| - values[1] = Math.asin(matrixR[7]); // beta [-pi/2, pi/2]
|
| - values[2] = -Math.PI / 2; // gamma = -pi/2
|
| - } else if (matrixR[6] < 0) { // cos(gamma) == 0, cos(beta) < 0
|
| - values[0] = Math.atan2(matrixR[1], -matrixR[4]);
|
| - values[1] = -Math.asin(matrixR[7]);
|
| - values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi,-pi/2) U (pi/2,pi)
|
| - values[2] = -Math.PI / 2; // gamma = -pi/2
|
| - } else { // R[6] == 0, cos(beta) == 0
|
| - // gimbal lock discontinuity
|
| - values[0] = Math.atan2(matrixR[3], matrixR[0]);
|
| - values[1] = (matrixR[7] > 0) ? Math.PI / 2 : -Math.PI / 2; // beta = +-pi/2
|
| - values[2] = 0; // gamma = 0
|
| - }
|
| - }
|
| -
|
| - // alpha is in [-pi, pi], make sure it is in [0, 2*pi).
|
| - if (values[0] < 0) {
|
| - values[0] += 2 * Math.PI; // alpha [0, 2*pi)
|
| - }
|
| -
|
| - return values;
|
| - }
|
| -
|
| - /*
|
| - * Converts a given rotation vector to its Euler angles representation. The angles
|
| - * are in degrees.
|
| - */
|
| - public void convertRotationVectorToAngles(float[] rotationVector, double[] angles) {
|
| - if (rotationVector.length > 4) {
|
| - // On some Samsung devices SensorManager.getRotationMatrixFromVector
|
| - // appears to throw an exception if rotation vector has length > 4.
|
| - // For the purposes of this class the first 4 values of the
|
| - // rotation vector are sufficient (see crbug.com/335298 for details).
|
| - System.arraycopy(rotationVector, 0, mTruncatedRotationVector, 0, 4);
|
| - SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix,
|
| - mTruncatedRotationVector);
|
| - } else {
|
| - SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rotationVector);
|
| - }
|
| - computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, angles);
|
| - for (int i = 0; i < 3; i++) {
|
| - angles[i] = Math.toDegrees(angles[i]);
|
| - }
|
| - }
|
| -
|
| - private void getOrientationFromGeomagneticVectors(float[] acceleration, float[] magnetic) {
|
| - if (acceleration == null || magnetic == null) {
|
| - return;
|
| - }
|
| - if (!SensorManager.getRotationMatrix(mDeviceRotationMatrix, null, acceleration, magnetic)) {
|
| - return;
|
| - }
|
| - computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, mRotationAngles);
|
| -
|
| - gotOrientation(Math.toDegrees(mRotationAngles[0]),
|
| - Math.toDegrees(mRotationAngles[1]),
|
| - Math.toDegrees(mRotationAngles[2]));
|
| - }
|
| -
|
| - private SensorManagerProxy getSensorManagerProxy() {
|
| - if (mSensorManagerProxy != null) {
|
| - return mSensorManagerProxy;
|
| - }
|
| -
|
| - ThreadUtils.assertOnUiThread();
|
| - SensorManager sensorManager =
|
| - (SensorManager) mAppContext.getSystemService(Context.SENSOR_SERVICE);
|
| -
|
| - if (sensorManager != null) {
|
| - mSensorManagerProxy = new SensorManagerProxyImpl(sensorManager);
|
| - }
|
| - return mSensorManagerProxy;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - void setSensorManagerProxy(SensorManagerProxy sensorManagerProxy) {
|
| - mSensorManagerProxy = sensorManagerProxy;
|
| - }
|
| -
|
| - private void setEventTypeActive(int eventType, boolean active) {
|
| - switch (eventType) {
|
| - case ConsumerType.ORIENTATION:
|
| - mDeviceOrientationIsActive = active;
|
| - mDeviceOrientationIsActiveWithBackupSensors = active
|
| - && (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C);
|
| - return;
|
| - case ConsumerType.ORIENTATION_ABSOLUTE:
|
| - mDeviceOrientationAbsoluteIsActive = active;
|
| - return;
|
| - case ConsumerType.MOTION:
|
| - mDeviceMotionIsActive = active;
|
| - return;
|
| - case ConsumerType.LIGHT:
|
| - mDeviceLightIsActive = active;
|
| - return;
|
| - }
|
| - }
|
| -
|
| - private void ensureRotationStructuresAllocated() {
|
| - if (mDeviceRotationMatrix == null) {
|
| - mDeviceRotationMatrix = new float[9];
|
| - }
|
| - if (mRotationAngles == null) {
|
| - mRotationAngles = new double[3];
|
| - }
|
| - if (mTruncatedRotationVector == null) {
|
| - mTruncatedRotationVector = new float[4];
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @param sensorTypes List of sensors to activate.
|
| - * @param rateInMicroseconds Intended delay (in microseconds) between sensor readings.
|
| - * @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 registerSensors(Set<Integer> sensorTypes, int rateInMicroseconds,
|
| - boolean failOnMissingSensor) {
|
| - Set<Integer> sensorsToActivate = new HashSet<Integer>(sensorTypes);
|
| - sensorsToActivate.removeAll(mActiveSensors);
|
| - if (sensorsToActivate.isEmpty()) return true;
|
| -
|
| - boolean success = false;
|
| - for (Integer sensorType : sensorsToActivate) {
|
| - boolean result = registerForSensorType(sensorType, rateInMicroseconds);
|
| - if (!result && failOnMissingSensor) {
|
| - // restore the previous state upon failure
|
| - unregisterSensors(sensorsToActivate);
|
| - return false;
|
| - }
|
| - if (result) {
|
| - mActiveSensors.add(sensorType);
|
| - success = true;
|
| - }
|
| - }
|
| - return success;
|
| - }
|
| -
|
| - private void unregisterSensors(Iterable<Integer> sensorTypes) {
|
| - for (Integer sensorType : sensorTypes) {
|
| - if (mActiveSensors.contains(sensorType)) {
|
| - getSensorManagerProxy().unregisterListener(this, sensorType);
|
| - mActiveSensors.remove(sensorType);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private boolean registerForSensorType(int type, int rateInMicroseconds) {
|
| - SensorManagerProxy sensorManager = getSensorManagerProxy();
|
| - if (sensorManager == null) {
|
| - return false;
|
| - }
|
| - return sensorManager.registerListener(this, type, rateInMicroseconds, getHandler());
|
| - }
|
| -
|
| - protected void gotOrientation(double alpha, double beta, double gamma) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotOrientation(mNativePtr, alpha, beta, gamma);
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected void gotOrientationAbsolute(double alpha, double beta, double gamma) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotOrientationAbsolute(mNativePtr, alpha, beta, gamma);
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected void gotAcceleration(double x, double y, double z) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotAcceleration(mNativePtr, x, y, z);
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected void gotAccelerationIncludingGravity(double x, double y, double z) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotAccelerationIncludingGravity(mNativePtr, x, y, z);
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected void gotRotationRate(double alpha, double beta, double gamma) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotRotationRate(mNativePtr, alpha, beta, gamma);
|
| - }
|
| - }
|
| - }
|
| -
|
| - protected void gotLight(double value) {
|
| - synchronized (mNativePtrLock) {
|
| - if (mNativePtr != 0) {
|
| - nativeGotLight(mNativePtr, value);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private Handler getHandler() {
|
| - // TODO(timvolodine): Remove the mHandlerLock when sure that getHandler is not called
|
| - // from multiple threads. This will be the case when device motion and device orientation
|
| - // use the same polling thread (also see crbug/234282).
|
| - synchronized (mHandlerLock) {
|
| - if (mHandler == null) {
|
| - HandlerThread thread = new HandlerThread("DeviceMotionAndOrientation");
|
| - thread.start();
|
| - mHandler = new Handler(thread.getLooper()); // blocks on thread start
|
| - }
|
| - return mHandler;
|
| - }
|
| - }
|
| -
|
| - @CalledByNative
|
| - static DeviceSensors getInstance(Context appContext) {
|
| - synchronized (sSingletonLock) {
|
| - if (sSingleton == null) {
|
| - sSingleton = new DeviceSensors(appContext);
|
| - }
|
| - return sSingleton;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Native JNI calls,
|
| - * see content/browser/device_sensors/sensor_manager_android.cc
|
| - */
|
| -
|
| - /**
|
| - * Orientation of the device with respect to its reference frame.
|
| - */
|
| - private native void nativeGotOrientation(
|
| - long nativeSensorManagerAndroid,
|
| - double alpha, double beta, double gamma);
|
| -
|
| - /**
|
| - * Absolute orientation of the device with respect to its reference frame.
|
| - */
|
| - private native void nativeGotOrientationAbsolute(
|
| - long nativeSensorManagerAndroid,
|
| - double alpha, double beta, double gamma);
|
| -
|
| - /**
|
| - * Linear acceleration without gravity of the device with respect to its body frame.
|
| - */
|
| - private native void nativeGotAcceleration(
|
| - long nativeSensorManagerAndroid,
|
| - double x, double y, double z);
|
| -
|
| - /**
|
| - * Acceleration including gravity of the device with respect to its body frame.
|
| - */
|
| - private native void nativeGotAccelerationIncludingGravity(
|
| - long nativeSensorManagerAndroid,
|
| - double x, double y, double z);
|
| -
|
| - /**
|
| - * Rotation rate of the device with respect to its body frame.
|
| - */
|
| - private native void nativeGotRotationRate(
|
| - long nativeSensorManagerAndroid,
|
| - double alpha, double beta, double gamma);
|
| -
|
| - /**
|
| - * Device Light value from Ambient Light sensors.
|
| - */
|
| - private native void nativeGotLight(
|
| - long nativeSensorManagerAndroid,
|
| - double value);
|
| -
|
| - /**
|
| - * Need the an interface for SensorManager for testing.
|
| - */
|
| - interface SensorManagerProxy {
|
| - public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
|
| - Handler handler);
|
| - public void unregisterListener(SensorEventListener listener, int sensorType);
|
| - }
|
| -
|
| - static class SensorManagerProxyImpl implements SensorManagerProxy {
|
| - private final SensorManager mSensorManager;
|
| -
|
| - SensorManagerProxyImpl(SensorManager sensorManager) {
|
| - mSensorManager = sensorManager;
|
| - }
|
| -
|
| - @Override
|
| - public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
|
| - Handler handler) {
|
| - List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
|
| - if (sensors.isEmpty()) {
|
| - return false;
|
| - }
|
| - return mSensorManager.registerListener(listener, sensors.get(0), rate, handler);
|
| - }
|
| -
|
| - @Override
|
| - public void unregisterListener(SensorEventListener listener, int sensorType) {
|
| - List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
|
| - if (sensors.isEmpty()) {
|
| - return;
|
| - }
|
| - try {
|
| - mSensorManager.unregisterListener(listener, sensors.get(0));
|
| - } catch (IllegalArgumentException e) {
|
| - // Suppress occasional exception on Digma iDxD* devices:
|
| - // Receiver not registered: android.hardware.SystemSensorManager$1
|
| - // See crbug.com/596453.
|
| - Log.w(TAG, "Failed to unregister device sensor " + sensors.get(0).getName());
|
| - }
|
| - }
|
| - }
|
| -
|
| -}
|
|
|