Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.device.sensors; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.hardware.Sensor; | 8 import android.hardware.Sensor; |
| 9 import android.hardware.SensorEvent; | 9 import android.hardware.SensorEvent; |
| 10 import android.hardware.SensorEventListener; | 10 import android.hardware.SensorEventListener; |
| 11 import android.hardware.SensorManager; | 11 import android.hardware.SensorManager; |
| 12 import android.os.Handler; | 12 import android.os.Handler; |
| 13 import android.os.HandlerThread; | 13 import android.os.HandlerThread; |
| 14 | 14 |
| 15 import org.chromium.base.CollectionUtil; | 15 import org.chromium.base.CollectionUtil; |
| 16 import org.chromium.base.Log; | 16 import org.chromium.base.Log; |
| 17 import org.chromium.base.ThreadUtils; | 17 import org.chromium.base.ThreadUtils; |
| 18 import org.chromium.base.VisibleForTesting; | 18 import org.chromium.base.VisibleForTesting; |
| 19 import org.chromium.base.annotations.CalledByNative; | 19 import org.chromium.base.annotations.CalledByNative; |
| 20 import org.chromium.base.annotations.JNINamespace; | 20 import org.chromium.base.annotations.JNINamespace; |
| 21 | 21 |
| 22 import java.util.HashSet; | 22 import java.util.HashSet; |
| 23 import java.util.List; | 23 import java.util.List; |
| 24 import java.util.Set; | 24 import java.util.Set; |
| 25 | 25 |
| 26 /** | 26 /** |
| 27 * Android implementation of the device {motion|orientation|light} APIs. | 27 * Android implementation of the device {motion|orientation|light} APIs. |
| 28 */ | 28 */ |
| 29 @JNINamespace("content") | 29 @JNINamespace("device") |
| 30 class DeviceSensors implements SensorEventListener { | 30 public class DeviceSensors implements SensorEventListener { |
| 31 | 31 private static final String TAG = "DeviceSensors"; |
| 32 private static final String TAG = "cr.DeviceSensors"; | |
| 33 | 32 |
| 34 // Matches kEnableExperimentalWebPlatformFeatures. | 33 // Matches kEnableExperimentalWebPlatformFeatures. |
| 35 private static final String EXPERIMENTAL_WEB_PLAFTORM_FEATURES = | 34 private static final String EXPERIMENTAL_WEB_PLAFTORM_FEATURES = |
| 36 "enable-experimental-web-platform-features"; | 35 "enable-experimental-web-platform-features"; |
| 37 | 36 |
| 38 // These fields are lazily initialized by getHandler(). | 37 // These fields are lazily initialized by getHandler(). |
| 39 private Thread mThread; | 38 private Thread mThread; |
| 40 private Handler mHandler; | 39 private Handler mHandler; |
| 41 | 40 |
| 42 // A reference to the application context in order to acquire the SensorServ ice. | 41 // A reference to the application context in order to acquire the SensorServ ice. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 64 // Holds Euler angles corresponding to the rotation matrix. | 63 // Holds Euler angles corresponding to the rotation matrix. |
| 65 private double[] mRotationAngles; | 64 private double[] mRotationAngles; |
| 66 | 65 |
| 67 // Lazily initialized when registering for notifications. | 66 // Lazily initialized when registering for notifications. |
| 68 private SensorManagerProxy mSensorManagerProxy; | 67 private SensorManagerProxy mSensorManagerProxy; |
| 69 | 68 |
| 70 // The only instance of that class and its associated lock. | 69 // The only instance of that class and its associated lock. |
| 71 private static DeviceSensors sSingleton; | 70 private static DeviceSensors sSingleton; |
| 72 private static Object sSingletonLock = new Object(); | 71 private static Object sSingletonLock = new Object(); |
| 73 | 72 |
| 74 static final Set<Integer> DEVICE_ORIENTATION_SENSORS_A = CollectionUtil.newH ashSet( | 73 public static final Set<Integer> DEVICE_ORIENTATION_SENSORS_A = |
|
timvolodine
2017/01/26 14:01:15
why does this have to be public? also below and th
ke.he
2017/01/26 15:33:22
With this patch, the package name of this class is
timvolodine
2017/01/31 07:13:15
I assume this is a temporary situation? Is it poss
| |
| 75 Sensor.TYPE_GAME_ROTATION_VECTOR); | 74 CollectionUtil.newHashSet(Sensor.TYPE_GAME_ROTATION_VECTOR); |
| 76 static final Set<Integer> DEVICE_ORIENTATION_SENSORS_B = CollectionUtil.newH ashSet( | 75 public static final Set<Integer> DEVICE_ORIENTATION_SENSORS_B = |
| 77 Sensor.TYPE_ROTATION_VECTOR); | 76 CollectionUtil.newHashSet(Sensor.TYPE_ROTATION_VECTOR); |
| 78 // Option C backup sensors are used when options A and B are not available. | 77 // Option C backup sensors are used when options A and B are not available. |
| 79 static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C = CollectionUtil.newH ashSet( | 78 public static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C = |
| 80 Sensor.TYPE_ACCELEROMETER, | 79 CollectionUtil.newHashSet(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAG NETIC_FIELD); |
| 81 Sensor.TYPE_MAGNETIC_FIELD); | 80 public static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS = |
| 82 static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS = CollectionUt il.newHashSet( | 81 CollectionUtil.newHashSet(Sensor.TYPE_ROTATION_VECTOR); |
| 83 Sensor.TYPE_ROTATION_VECTOR); | 82 public static final Set<Integer> DEVICE_MOTION_SENSORS = CollectionUtil.newH ashSet( |
| 84 static final Set<Integer> DEVICE_MOTION_SENSORS = CollectionUtil.newHashSet( | 83 Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_LINEAR_ACCELERATION, Sensor.T YPE_GYROSCOPE); |
| 85 Sensor.TYPE_ACCELEROMETER, | 84 public static final Set<Integer> DEVICE_LIGHT_SENSORS = |
| 86 Sensor.TYPE_LINEAR_ACCELERATION, | 85 CollectionUtil.newHashSet(Sensor.TYPE_LIGHT); |
| 87 Sensor.TYPE_GYROSCOPE); | |
| 88 static final Set<Integer> DEVICE_LIGHT_SENSORS = CollectionUtil.newHashSet( | |
| 89 Sensor.TYPE_LIGHT); | |
| 90 | 86 |
| 91 @VisibleForTesting | 87 @VisibleForTesting |
| 92 final Set<Integer> mActiveSensors = new HashSet<Integer>(); | 88 public final Set<Integer> mActiveSensors = new HashSet<Integer>(); |
| 93 final List<Set<Integer>> mOrientationSensorSets; | 89 public final List<Set<Integer>> mOrientationSensorSets; |
| 94 Set<Integer> mDeviceOrientationSensors; | 90 public Set<Integer> mDeviceOrientationSensors; |
| 95 boolean mDeviceLightIsActive; | 91 public boolean mDeviceLightIsActive; |
| 96 boolean mDeviceMotionIsActive; | 92 public boolean mDeviceMotionIsActive; |
| 97 boolean mDeviceOrientationIsActive; | 93 public boolean mDeviceOrientationIsActive; |
| 98 boolean mDeviceOrientationIsActiveWithBackupSensors; | 94 public boolean mDeviceOrientationIsActiveWithBackupSensors; |
| 99 boolean mDeviceOrientationAbsoluteIsActive; | 95 public boolean mDeviceOrientationAbsoluteIsActive; |
| 100 boolean mOrientationNotAvailable; | 96 public boolean mOrientationNotAvailable; |
| 101 | 97 |
| 102 protected DeviceSensors(Context context) { | 98 protected DeviceSensors(Context context) { |
| 103 mAppContext = context.getApplicationContext(); | 99 mAppContext = context.getApplicationContext(); |
| 104 | 100 |
| 105 mOrientationSensorSets = CollectionUtil.newArrayList(DEVICE_ORIENTATION_ SENSORS_A, | 101 mOrientationSensorSets = CollectionUtil.newArrayList(DEVICE_ORIENTATION_ SENSORS_A, |
| 106 DEVICE_ORIENTATION_ SENSORS_B, | 102 DEVICE_ORIENTATION_SENSORS_B, DEVICE_ORIENTATION_SENSORS_C); |
| 107 DEVICE_ORIENTATION_ SENSORS_C); | |
| 108 } | 103 } |
| 109 | 104 |
| 110 // For orientation we use a 3-way fallback approach where up to 3 different sets of sensors | 105 // For orientation we use a 3-way fallback approach where up to 3 different sets of sensors |
| 111 // are attempted if necessary. The sensors to be used for orientation are de termined in the | 106 // are attempted if necessary. The sensors to be used for orientation are de termined in the |
| 112 // following order: | 107 // following order: |
| 113 // A: GAME_ROTATION_VECTOR (relative) | 108 // A: GAME_ROTATION_VECTOR (relative) |
| 114 // B: ROTATION_VECTOR (absolute) | 109 // B: ROTATION_VECTOR (absolute) |
| 115 // C: combination of ACCELEROMETER and MAGNETIC_FIELD (absolute) | 110 // C: combination of ACCELEROMETER and MAGNETIC_FIELD (absolute) |
| 116 // Some of the sensors may not be available depending on the device and Andr oid version, so | 111 // Some of the sensors may not be available depending on the device and Andr oid version, so |
| 117 // the 3-way fallback ensures selection of the best possible option. | 112 // the 3-way fallback ensures selection of the best possible option. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 @CalledByNative | 148 @CalledByNative |
| 154 public boolean start(long nativePtr, int eventType, int rateInMicroseconds) { | 149 public boolean start(long nativePtr, int eventType, int rateInMicroseconds) { |
| 155 boolean success = false; | 150 boolean success = false; |
| 156 synchronized (mNativePtrLock) { | 151 synchronized (mNativePtrLock) { |
| 157 switch (eventType) { | 152 switch (eventType) { |
| 158 case ConsumerType.ORIENTATION: | 153 case ConsumerType.ORIENTATION: |
| 159 success = registerOrientationSensorsWithFallback(rateInMicro seconds); | 154 success = registerOrientationSensorsWithFallback(rateInMicro seconds); |
| 160 break; | 155 break; |
| 161 case ConsumerType.ORIENTATION_ABSOLUTE: | 156 case ConsumerType.ORIENTATION_ABSOLUTE: |
| 162 ensureRotationStructuresAllocated(); | 157 ensureRotationStructuresAllocated(); |
| 163 success = registerSensors(DEVICE_ORIENTATION_ABSOLUTE_SENSOR S, | 158 success = registerSensors( |
| 164 rateInMicroseconds, true); | 159 DEVICE_ORIENTATION_ABSOLUTE_SENSORS, rateInMicroseco nds, true); |
| 165 break; | 160 break; |
| 166 case ConsumerType.MOTION: | 161 case ConsumerType.MOTION: |
| 167 // note: device motion spec does not require all sensors to be available | 162 // note: device motion spec does not require all sensors to be available |
| 168 success = registerSensors(DEVICE_MOTION_SENSORS, rateInMicro seconds, false); | 163 success = registerSensors(DEVICE_MOTION_SENSORS, rateInMicro seconds, false); |
| 169 break; | 164 break; |
| 170 case ConsumerType.LIGHT: | 165 case ConsumerType.LIGHT: |
| 171 success = registerSensors(DEVICE_LIGHT_SENSORS, rateInMicros econds, true); | 166 success = registerSensors(DEVICE_LIGHT_SENSORS, rateInMicros econds, true); |
| 172 break; | 167 break; |
| 173 default: | 168 default: |
| 174 Log.e(TAG, "Unknown event type: %d", eventType); | 169 Log.e(TAG, "Unknown event type: %d", eventType); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 197 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_A) { | 192 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_A) { |
| 198 return OrientationSensorType.GAME_ROTATION_VECTOR; | 193 return OrientationSensorType.GAME_ROTATION_VECTOR; |
| 199 } | 194 } |
| 200 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) { | 195 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) { |
| 201 return OrientationSensorType.ROTATION_VECTOR; | 196 return OrientationSensorType.ROTATION_VECTOR; |
| 202 } | 197 } |
| 203 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C) { | 198 if (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C) { |
| 204 return OrientationSensorType.ACCELEROMETER_MAGNETIC; | 199 return OrientationSensorType.ACCELEROMETER_MAGNETIC; |
| 205 } | 200 } |
| 206 | 201 |
| 207 assert false; // should never happen | 202 assert false; // should never happen |
| 208 return OrientationSensorType.NOT_AVAILABLE; | 203 return OrientationSensorType.NOT_AVAILABLE; |
| 209 } | 204 } |
| 210 | 205 |
| 211 /** | 206 /** |
| 212 * Stop listening to sensors for a given event type. Ensures that sensors ar e not disabled | 207 * Stop listening to sensors for a given event type. Ensures that sensors ar e not disabled |
| 213 * if they are still in use by a different event type. | 208 * if they are still in use by a different event type. |
| 214 * | 209 * |
| 215 * @param eventType Type of event to listen to, can be either DEVICE_ORIENTA TION or | 210 * @param eventType Type of event to listen to, can be either DEVICE_ORIENTA TION or |
| 216 * DEVICE_MOTION or DEVICE_LIGHT. | 211 * DEVICE_MOTION or DEVICE_LIGHT. |
| 217 * We strictly guarantee that the corresponding native*() methods will not b e called | 212 * We strictly guarantee that the corresponding native*() methods will not b e called |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 public void onAccuracyChanged(Sensor sensor, int accuracy) { | 248 public void onAccuracyChanged(Sensor sensor, int accuracy) { |
| 254 // Nothing | 249 // Nothing |
| 255 } | 250 } |
| 256 | 251 |
| 257 @Override | 252 @Override |
| 258 public void onSensorChanged(SensorEvent event) { | 253 public void onSensorChanged(SensorEvent event) { |
| 259 sensorChanged(event.sensor.getType(), event.values); | 254 sensorChanged(event.sensor.getType(), event.values); |
| 260 } | 255 } |
| 261 | 256 |
| 262 @VisibleForTesting | 257 @VisibleForTesting |
| 263 void sensorChanged(int type, float[] values) { | 258 public void sensorChanged(int type, float[] values) { |
| 264 switch (type) { | 259 switch (type) { |
| 265 case Sensor.TYPE_ACCELEROMETER: | 260 case Sensor.TYPE_ACCELEROMETER: |
| 266 if (mDeviceMotionIsActive) { | 261 if (mDeviceMotionIsActive) { |
| 267 gotAccelerationIncludingGravity(values[0], values[1], values [2]); | 262 gotAccelerationIncludingGravity(values[0], values[1], values [2]); |
| 268 } | 263 } |
| 269 if (mDeviceOrientationIsActiveWithBackupSensors) { | 264 if (mDeviceOrientationIsActiveWithBackupSensors) { |
| 270 getOrientationFromGeomagneticVectors(values, mMagneticFieldV ector); | 265 getOrientationFromGeomagneticVectors(values, mMagneticFieldV ector); |
| 271 } | 266 } |
| 272 break; | 267 break; |
| 273 case Sensor.TYPE_LINEAR_ACCELERATION: | 268 case Sensor.TYPE_LINEAR_ACCELERATION: |
| 274 if (mDeviceMotionIsActive) { | 269 if (mDeviceMotionIsActive) { |
| 275 gotAcceleration(values[0], values[1], values[2]); | 270 gotAcceleration(values[0], values[1], values[2]); |
| 276 } | 271 } |
| 277 break; | 272 break; |
| 278 case Sensor.TYPE_GYROSCOPE: | 273 case Sensor.TYPE_GYROSCOPE: |
| 279 if (mDeviceMotionIsActive) { | 274 if (mDeviceMotionIsActive) { |
| 280 gotRotationRate(values[0], values[1], values[2]); | 275 gotRotationRate(values[0], values[1], values[2]); |
| 281 } | 276 } |
| 282 break; | 277 break; |
| 283 case Sensor.TYPE_ROTATION_VECTOR: | 278 case Sensor.TYPE_ROTATION_VECTOR: |
| 284 if (mDeviceOrientationAbsoluteIsActive) { | 279 if (mDeviceOrientationAbsoluteIsActive) { |
| 285 convertRotationVectorToAngles(values, mRotationAngles); | 280 convertRotationVectorToAngles(values, mRotationAngles); |
| 286 gotOrientationAbsolute(mRotationAngles[0], mRotationAngles[1 ], | 281 gotOrientationAbsolute( |
| 287 mRotationAngles[2]); | 282 mRotationAngles[0], mRotationAngles[1], mRotationAng les[2]); |
| 288 } | 283 } |
| 289 if (mDeviceOrientationIsActive | 284 if (mDeviceOrientationIsActive |
| 290 && mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSO RS_B) { | 285 && mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSO RS_B) { |
| 291 if (!mDeviceOrientationAbsoluteIsActive) { | 286 if (!mDeviceOrientationAbsoluteIsActive) { |
| 292 // only compute if not already computed for absolute ori entation above. | 287 // only compute if not already computed for absolute ori entation above. |
| 293 convertRotationVectorToAngles(values, mRotationAngles); | 288 convertRotationVectorToAngles(values, mRotationAngles); |
| 294 } | 289 } |
| 295 gotOrientation(mRotationAngles[0], mRotationAngles[1], mRota tionAngles[2]); | 290 gotOrientation(mRotationAngles[0], mRotationAngles[1], mRota tionAngles[2]); |
| 296 } | 291 } |
| 297 break; | 292 break; |
| 298 case Sensor.TYPE_GAME_ROTATION_VECTOR: | 293 case Sensor.TYPE_GAME_ROTATION_VECTOR: |
| 299 if (mDeviceOrientationIsActive) { | 294 if (mDeviceOrientationIsActive) { |
| 300 convertRotationVectorToAngles(values, mRotationAngles); | 295 convertRotationVectorToAngles(values, mRotationAngles); |
| 301 gotOrientation(mRotationAngles[0], mRotationAngles[1], mRota tionAngles[2]); | 296 gotOrientation(mRotationAngles[0], mRotationAngles[1], mRota tionAngles[2]); |
| 302 } | 297 } |
| 303 break; | 298 break; |
| 304 case Sensor.TYPE_MAGNETIC_FIELD: | 299 case Sensor.TYPE_MAGNETIC_FIELD: |
| 305 if (mDeviceOrientationIsActiveWithBackupSensors) { | 300 if (mDeviceOrientationIsActiveWithBackupSensors) { |
| 306 if (mMagneticFieldVector == null) { | 301 if (mMagneticFieldVector == null) { |
| 307 mMagneticFieldVector = new float[3]; | 302 mMagneticFieldVector = new float[3]; |
| 308 } | 303 } |
| 309 System.arraycopy(values, 0, mMagneticFieldVector, 0, | 304 System.arraycopy( |
| 310 mMagneticFieldVector.length); | 305 values, 0, mMagneticFieldVector, 0, mMagneticFieldVe ctor.length); |
| 311 } | 306 } |
| 312 break; | 307 break; |
| 313 case Sensor.TYPE_LIGHT: | 308 case Sensor.TYPE_LIGHT: |
| 314 if (mDeviceLightIsActive) { | 309 if (mDeviceLightIsActive) { |
| 315 gotLight(values[0]); | 310 gotLight(values[0]); |
| 316 } | 311 } |
| 317 break; | 312 break; |
| 318 default: | 313 default: |
| 319 // Unexpected | 314 // Unexpected |
| 320 return; | 315 return; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 float[] matrixR, double[] values) { | 358 float[] matrixR, double[] values) { |
| 364 /* | 359 /* |
| 365 * 3x3 (length=9) case: | 360 * 3x3 (length=9) case: |
| 366 * / R[ 0] R[ 1] R[ 2] \ | 361 * / R[ 0] R[ 1] R[ 2] \ |
| 367 * | R[ 3] R[ 4] R[ 5] | | 362 * | R[ 3] R[ 4] R[ 5] | |
| 368 * \ R[ 6] R[ 7] R[ 8] / | 363 * \ R[ 6] R[ 7] R[ 8] / |
| 369 * | 364 * |
| 370 */ | 365 */ |
| 371 if (matrixR.length != 9) return values; | 366 if (matrixR.length != 9) return values; |
| 372 | 367 |
| 373 if (matrixR[8] > 0) { // cos(beta) > 0 | 368 if (matrixR[8] > 0) { // cos(beta) > 0 |
| 374 values[0] = Math.atan2(-matrixR[1], matrixR[4]); | 369 values[0] = Math.atan2(-matrixR[1], matrixR[4]); |
| 375 values[1] = Math.asin(matrixR[7]); // beta (-pi/2, p i/2) | 370 values[1] = Math.asin(matrixR[7]); // beta (-pi/2, pi/2) |
|
timvolodine
2017/01/26 14:01:15
the alignment here was actually done on purpose fo
ke.he
2017/01/26 15:33:22
The format is changed by "git cl format", I'll kee
| |
| 376 values[2] = Math.atan2(-matrixR[6], matrixR[8]); // gamma (-pi/2, pi/2) | 371 values[2] = Math.atan2(-matrixR[6], matrixR[8]); // gamma (-pi/2, pi /2) |
| 377 } else if (matrixR[8] < 0) { // cos(beta) < 0 | 372 } else if (matrixR[8] < 0) { // cos(beta) < 0 |
| 378 values[0] = Math.atan2(matrixR[1], -matrixR[4]); | 373 values[0] = Math.atan2(matrixR[1], -matrixR[4]); |
| 379 values[1] = -Math.asin(matrixR[7]); | 374 values[1] = -Math.asin(matrixR[7]); |
| 380 values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi,-pi /2) U (pi/2,pi) | 375 values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi,-pi /2) U (pi/2,pi) |
| 381 values[2] = Math.atan2(matrixR[6], -matrixR[8]); // gamma (-pi/2, pi/2) | 376 values[2] = Math.atan2(matrixR[6], -matrixR[8]); // gamma (-pi/2, pi /2) |
| 382 } else { // R[8] == 0 | 377 } else { // R[8] == 0 |
| 383 if (matrixR[6] > 0) { // cos(gamma) == 0, cos(beta) > 0 | 378 if (matrixR[6] > 0) { // cos(gamma) == 0, cos(beta) > 0 |
| 384 values[0] = Math.atan2(-matrixR[1], matrixR[4]); | 379 values[0] = Math.atan2(-matrixR[1], matrixR[4]); |
| 385 values[1] = Math.asin(matrixR[7]); // beta [-pi/2, pi/2] | 380 values[1] = Math.asin(matrixR[7]); // beta [-pi/2, pi/2] |
| 386 values[2] = -Math.PI / 2; // gamma = -pi/2 | 381 values[2] = -Math.PI / 2; // gamma = -pi/2 |
| 387 } else if (matrixR[6] < 0) { // cos(gamma) == 0, cos(beta) < 0 | 382 } else if (matrixR[6] < 0) { // cos(gamma) == 0, cos(beta) < 0 |
| 388 values[0] = Math.atan2(matrixR[1], -matrixR[4]); | 383 values[0] = Math.atan2(matrixR[1], -matrixR[4]); |
| 389 values[1] = -Math.asin(matrixR[7]); | 384 values[1] = -Math.asin(matrixR[7]); |
| 390 values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi ,-pi/2) U (pi/2,pi) | 385 values[1] += (values[1] >= 0) ? -Math.PI : Math.PI; // beta [-pi ,-pi/2) U (pi/2,pi) |
| 391 values[2] = -Math.PI / 2; // gamma = - pi/2 | 386 values[2] = -Math.PI / 2; // gamma = -pi/2 |
| 392 } else { // R[6] == 0, cos(beta) == 0 | 387 } else { // R[6] == 0, cos(beta) == 0 |
| 393 // gimbal lock discontinuity | 388 // gimbal lock discontinuity |
| 394 values[0] = Math.atan2(matrixR[3], matrixR[0]); | 389 values[0] = Math.atan2(matrixR[3], matrixR[0]); |
| 395 values[1] = (matrixR[7] > 0) ? Math.PI / 2 : -Math.PI / 2; // b eta = +-pi/2 | 390 values[1] = (matrixR[7] > 0) ? Math.PI / 2 : -Math.PI / 2; // be ta = +-pi/2 |
| 396 values[2] = 0; // g amma = 0 | 391 values[2] = 0; // gamma = 0 |
| 397 } | 392 } |
| 398 } | 393 } |
| 399 | 394 |
| 400 // alpha is in [-pi, pi], make sure it is in [0, 2*pi). | 395 // alpha is in [-pi, pi], make sure it is in [0, 2*pi). |
| 401 if (values[0] < 0) { | 396 if (values[0] < 0) { |
| 402 values[0] += 2 * Math.PI; // alpha [0, 2*pi) | 397 values[0] += 2 * Math.PI; // alpha [0, 2*pi) |
| 403 } | 398 } |
| 404 | 399 |
| 405 return values; | 400 return values; |
| 406 } | 401 } |
| 407 | 402 |
| 408 /* | 403 /* |
| 409 * Converts a given rotation vector to its Euler angles representation. The angles | 404 * Converts a given rotation vector to its Euler angles representation. The angles |
| 410 * are in degrees. | 405 * are in degrees. |
| 411 */ | 406 */ |
| 412 public void convertRotationVectorToAngles(float[] rotationVector, double[] a ngles) { | 407 public void convertRotationVectorToAngles(float[] rotationVector, double[] a ngles) { |
| 413 if (rotationVector.length > 4) { | 408 if (rotationVector.length > 4) { |
| 414 // On some Samsung devices SensorManager.getRotationMatrixFromVector | 409 // On some Samsung devices SensorManager.getRotationMatrixFromVector |
| 415 // appears to throw an exception if rotation vector has length > 4. | 410 // appears to throw an exception if rotation vector has length > 4. |
| 416 // For the purposes of this class the first 4 values of the | 411 // For the purposes of this class the first 4 values of the |
| 417 // rotation vector are sufficient (see crbug.com/335298 for details) . | 412 // rotation vector are sufficient (see crbug.com/335298 for details) . |
| 418 System.arraycopy(rotationVector, 0, mTruncatedRotationVector, 0, 4); | 413 System.arraycopy(rotationVector, 0, mTruncatedRotationVector, 0, 4); |
| 419 SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, | 414 SensorManager.getRotationMatrixFromVector( |
| 420 mTruncatedRotationVector); | 415 mDeviceRotationMatrix, mTruncatedRotationVector); |
| 421 } else { | 416 } else { |
| 422 SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rot ationVector); | 417 SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rot ationVector); |
| 423 } | 418 } |
| 424 computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, angles ); | 419 computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, angles ); |
| 425 for (int i = 0; i < 3; i++) { | 420 for (int i = 0; i < 3; i++) { |
| 426 angles[i] = Math.toDegrees(angles[i]); | 421 angles[i] = Math.toDegrees(angles[i]); |
| 427 } | 422 } |
| 428 } | 423 } |
| 429 | 424 |
| 430 private void getOrientationFromGeomagneticVectors(float[] acceleration, floa t[] magnetic) { | 425 private void getOrientationFromGeomagneticVectors(float[] acceleration, floa t[] magnetic) { |
| 431 if (acceleration == null || magnetic == null) { | 426 if (acceleration == null || magnetic == null) { |
| 432 return; | 427 return; |
| 433 } | 428 } |
| 434 if (!SensorManager.getRotationMatrix(mDeviceRotationMatrix, null, accele ration, magnetic)) { | 429 if (!SensorManager.getRotationMatrix(mDeviceRotationMatrix, null, accele ration, magnetic)) { |
| 435 return; | 430 return; |
| 436 } | 431 } |
| 437 computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, mRotat ionAngles); | 432 computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, mRotat ionAngles); |
| 438 | 433 |
| 439 gotOrientation(Math.toDegrees(mRotationAngles[0]), | 434 gotOrientation(Math.toDegrees(mRotationAngles[0]), Math.toDegrees(mRotat ionAngles[1]), |
| 440 Math.toDegrees(mRotationAngles[1]), | 435 Math.toDegrees(mRotationAngles[2])); |
| 441 Math.toDegrees(mRotationAngles[2])); | |
| 442 } | 436 } |
| 443 | 437 |
| 444 private SensorManagerProxy getSensorManagerProxy() { | 438 private SensorManagerProxy getSensorManagerProxy() { |
| 445 if (mSensorManagerProxy != null) { | 439 if (mSensorManagerProxy != null) { |
| 446 return mSensorManagerProxy; | 440 return mSensorManagerProxy; |
| 447 } | 441 } |
| 448 | 442 |
| 449 ThreadUtils.assertOnUiThread(); | 443 ThreadUtils.assertOnUiThread(); |
| 450 SensorManager sensorManager = | 444 SensorManager sensorManager = |
| 451 (SensorManager) mAppContext.getSystemService(Context.SENSOR_SERV ICE); | 445 (SensorManager) mAppContext.getSystemService(Context.SENSOR_SERV ICE); |
| 452 | 446 |
| 453 if (sensorManager != null) { | 447 if (sensorManager != null) { |
| 454 mSensorManagerProxy = new SensorManagerProxyImpl(sensorManager); | 448 mSensorManagerProxy = new SensorManagerProxyImpl(sensorManager); |
| 455 } | 449 } |
| 456 return mSensorManagerProxy; | 450 return mSensorManagerProxy; |
| 457 } | 451 } |
| 458 | 452 |
| 459 @VisibleForTesting | 453 @VisibleForTesting |
| 460 void setSensorManagerProxy(SensorManagerProxy sensorManagerProxy) { | 454 public void setSensorManagerProxy(SensorManagerProxy sensorManagerProxy) { |
| 461 mSensorManagerProxy = sensorManagerProxy; | 455 mSensorManagerProxy = sensorManagerProxy; |
| 462 } | 456 } |
| 463 | 457 |
| 464 private void setEventTypeActive(int eventType, boolean active) { | 458 private void setEventTypeActive(int eventType, boolean active) { |
| 465 switch (eventType) { | 459 switch (eventType) { |
| 466 case ConsumerType.ORIENTATION: | 460 case ConsumerType.ORIENTATION: |
| 467 mDeviceOrientationIsActive = active; | 461 mDeviceOrientationIsActive = active; |
| 468 mDeviceOrientationIsActiveWithBackupSensors = active | 462 mDeviceOrientationIsActiveWithBackupSensors = |
| 469 && (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENS ORS_C); | 463 active && (mDeviceOrientationSensors == DEVICE_ORIENTATI ON_SENSORS_C); |
| 470 return; | 464 return; |
| 471 case ConsumerType.ORIENTATION_ABSOLUTE: | 465 case ConsumerType.ORIENTATION_ABSOLUTE: |
| 472 mDeviceOrientationAbsoluteIsActive = active; | 466 mDeviceOrientationAbsoluteIsActive = active; |
| 473 return; | 467 return; |
| 474 case ConsumerType.MOTION: | 468 case ConsumerType.MOTION: |
| 475 mDeviceMotionIsActive = active; | 469 mDeviceMotionIsActive = active; |
| 476 return; | 470 return; |
| 477 case ConsumerType.LIGHT: | 471 case ConsumerType.LIGHT: |
| 478 mDeviceLightIsActive = active; | 472 mDeviceLightIsActive = active; |
| 479 return; | 473 return; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 492 } | 486 } |
| 493 } | 487 } |
| 494 | 488 |
| 495 /** | 489 /** |
| 496 * @param sensorTypes List of sensors to activate. | 490 * @param sensorTypes List of sensors to activate. |
| 497 * @param rateInMicroseconds Intended delay (in microseconds) between sensor readings. | 491 * @param rateInMicroseconds Intended delay (in microseconds) between sensor readings. |
| 498 * @param failOnMissingSensor If true the method returns true only if all se nsors could be | 492 * @param failOnMissingSensor If true the method returns true only if all se nsors could be |
| 499 * activated. When false the method return true i f at least one | 493 * activated. When false the method return true i f at least one |
| 500 * sensor in sensorTypes could be activated. | 494 * sensor in sensorTypes could be activated. |
| 501 */ | 495 */ |
| 502 private boolean registerSensors(Set<Integer> sensorTypes, int rateInMicrosec onds, | 496 private boolean registerSensors( |
| 503 boolean failOnMissingSensor) { | 497 Set<Integer> sensorTypes, int rateInMicroseconds, boolean failOnMiss ingSensor) { |
| 504 Set<Integer> sensorsToActivate = new HashSet<Integer>(sensorTypes); | 498 Set<Integer> sensorsToActivate = new HashSet<Integer>(sensorTypes); |
| 505 sensorsToActivate.removeAll(mActiveSensors); | 499 sensorsToActivate.removeAll(mActiveSensors); |
| 506 if (sensorsToActivate.isEmpty()) return true; | 500 if (sensorsToActivate.isEmpty()) return true; |
| 507 | 501 |
| 508 boolean success = false; | 502 boolean success = false; |
| 509 for (Integer sensorType : sensorsToActivate) { | 503 for (Integer sensorType : sensorsToActivate) { |
| 510 boolean result = registerForSensorType(sensorType, rateInMicrosecond s); | 504 boolean result = registerForSensorType(sensorType, rateInMicrosecond s); |
| 511 if (!result && failOnMissingSensor) { | 505 if (!result && failOnMissingSensor) { |
| 512 // restore the previous state upon failure | 506 // restore the previous state upon failure |
| 513 unregisterSensors(sensorsToActivate); | 507 unregisterSensors(sensorsToActivate); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 587 } | 581 } |
| 588 | 582 |
| 589 private Handler getHandler() { | 583 private Handler getHandler() { |
| 590 // TODO(timvolodine): Remove the mHandlerLock when sure that getHandler is not called | 584 // TODO(timvolodine): Remove the mHandlerLock when sure that getHandler is not called |
| 591 // from multiple threads. This will be the case when device motion and d evice orientation | 585 // from multiple threads. This will be the case when device motion and d evice orientation |
| 592 // use the same polling thread (also see crbug/234282). | 586 // use the same polling thread (also see crbug/234282). |
| 593 synchronized (mHandlerLock) { | 587 synchronized (mHandlerLock) { |
| 594 if (mHandler == null) { | 588 if (mHandler == null) { |
| 595 HandlerThread thread = new HandlerThread("DeviceMotionAndOrienta tion"); | 589 HandlerThread thread = new HandlerThread("DeviceMotionAndOrienta tion"); |
| 596 thread.start(); | 590 thread.start(); |
| 597 mHandler = new Handler(thread.getLooper()); // blocks on thread start | 591 mHandler = new Handler(thread.getLooper()); // blocks on thread start |
| 598 } | 592 } |
| 599 return mHandler; | 593 return mHandler; |
| 600 } | 594 } |
| 601 } | 595 } |
| 602 | 596 |
| 603 @CalledByNative | 597 @CalledByNative |
| 604 static DeviceSensors getInstance(Context appContext) { | 598 static DeviceSensors getInstance(Context appContext) { |
| 605 synchronized (sSingletonLock) { | 599 synchronized (sSingletonLock) { |
| 606 if (sSingleton == null) { | 600 if (sSingleton == null) { |
| 607 sSingleton = new DeviceSensors(appContext); | 601 sSingleton = new DeviceSensors(appContext); |
| 608 } | 602 } |
| 609 return sSingleton; | 603 return sSingleton; |
| 610 } | 604 } |
| 611 } | 605 } |
| 612 | 606 |
| 613 /** | 607 /** |
| 614 * Native JNI calls, | 608 * Native JNI calls, |
| 615 * see content/browser/device_sensors/sensor_manager_android.cc | 609 * see device/sensors/sensor_manager_android.cc |
| 616 */ | 610 */ |
| 617 | 611 |
| 618 /** | 612 /** |
| 619 * Orientation of the device with respect to its reference frame. | 613 * Orientation of the device with respect to its reference frame. |
| 620 */ | 614 */ |
| 621 private native void nativeGotOrientation( | 615 private native void nativeGotOrientation( |
| 622 long nativeSensorManagerAndroid, | 616 long nativeSensorManagerAndroid, double alpha, double beta, double g amma); |
| 623 double alpha, double beta, double gamma); | |
| 624 | 617 |
| 625 /** | 618 /** |
| 626 * Absolute orientation of the device with respect to its reference frame. | 619 * Absolute orientation of the device with respect to its reference frame. |
| 627 */ | 620 */ |
| 628 private native void nativeGotOrientationAbsolute( | 621 private native void nativeGotOrientationAbsolute( |
| 629 long nativeSensorManagerAndroid, | 622 long nativeSensorManagerAndroid, double alpha, double beta, double g amma); |
| 630 double alpha, double beta, double gamma); | |
| 631 | 623 |
| 632 /** | 624 /** |
| 633 * Linear acceleration without gravity of the device with respect to its bod y frame. | 625 * Linear acceleration without gravity of the device with respect to its bod y frame. |
| 634 */ | 626 */ |
| 635 private native void nativeGotAcceleration( | 627 private native void nativeGotAcceleration( |
| 636 long nativeSensorManagerAndroid, | 628 long nativeSensorManagerAndroid, double x, double y, double z); |
| 637 double x, double y, double z); | |
| 638 | 629 |
| 639 /** | 630 /** |
| 640 * Acceleration including gravity of the device with respect to its body fra me. | 631 * Acceleration including gravity of the device with respect to its body fra me. |
| 641 */ | 632 */ |
| 642 private native void nativeGotAccelerationIncludingGravity( | 633 private native void nativeGotAccelerationIncludingGravity( |
| 643 long nativeSensorManagerAndroid, | 634 long nativeSensorManagerAndroid, double x, double y, double z); |
| 644 double x, double y, double z); | |
| 645 | 635 |
| 646 /** | 636 /** |
| 647 * Rotation rate of the device with respect to its body frame. | 637 * Rotation rate of the device with respect to its body frame. |
| 648 */ | 638 */ |
| 649 private native void nativeGotRotationRate( | 639 private native void nativeGotRotationRate( |
| 650 long nativeSensorManagerAndroid, | 640 long nativeSensorManagerAndroid, double alpha, double beta, double g amma); |
| 651 double alpha, double beta, double gamma); | |
| 652 | 641 |
| 653 /** | 642 /** |
| 654 * Device Light value from Ambient Light sensors. | 643 * Device Light value from Ambient Light sensors. |
| 655 */ | 644 */ |
| 656 private native void nativeGotLight( | 645 private native void nativeGotLight(long nativeSensorManagerAndroid, double v alue); |
| 657 long nativeSensorManagerAndroid, | |
| 658 double value); | |
| 659 | 646 |
| 660 /** | 647 /** |
| 661 * Need the an interface for SensorManager for testing. | 648 * Need the an interface for SensorManager for testing. |
| 662 */ | 649 */ |
| 663 interface SensorManagerProxy { | 650 public interface SensorManagerProxy { |
| 664 public boolean registerListener(SensorEventListener listener, int sensor Type, int rate, | 651 public boolean registerListener( |
| 665 Handler handler); | 652 SensorEventListener listener, int sensorType, int rate, Handler handler); |
| 666 public void unregisterListener(SensorEventListener listener, int sensorT ype); | 653 public void unregisterListener(SensorEventListener listener, int sensorT ype); |
| 667 } | 654 } |
| 668 | 655 |
| 669 static class SensorManagerProxyImpl implements SensorManagerProxy { | 656 static class SensorManagerProxyImpl implements SensorManagerProxy { |
| 670 private final SensorManager mSensorManager; | 657 private final SensorManager mSensorManager; |
| 671 | 658 |
| 672 SensorManagerProxyImpl(SensorManager sensorManager) { | 659 SensorManagerProxyImpl(SensorManager sensorManager) { |
| 673 mSensorManager = sensorManager; | 660 mSensorManager = sensorManager; |
| 674 } | 661 } |
| 675 | 662 |
| 676 @Override | 663 @Override |
| 677 public boolean registerListener(SensorEventListener listener, int sensor Type, int rate, | 664 public boolean registerListener( |
| 678 Handler handler) { | 665 SensorEventListener listener, int sensorType, int rate, Handler handler) { |
| 679 List<Sensor> sensors = mSensorManager.getSensorList(sensorType); | 666 List<Sensor> sensors = mSensorManager.getSensorList(sensorType); |
| 680 if (sensors.isEmpty()) { | 667 if (sensors.isEmpty()) { |
| 681 return false; | 668 return false; |
| 682 } | 669 } |
| 683 return mSensorManager.registerListener(listener, sensors.get(0), rat e, handler); | 670 return mSensorManager.registerListener(listener, sensors.get(0), rat e, handler); |
| 684 } | 671 } |
| 685 | 672 |
| 686 @Override | 673 @Override |
| 687 public void unregisterListener(SensorEventListener listener, int sensorT ype) { | 674 public void unregisterListener(SensorEventListener listener, int sensorT ype) { |
| 688 List<Sensor> sensors = mSensorManager.getSensorList(sensorType); | 675 List<Sensor> sensors = mSensorManager.getSensorList(sensorType); |
| 689 if (sensors.isEmpty()) { | 676 if (sensors.isEmpty()) { |
| 690 return; | 677 return; |
| 691 } | 678 } |
| 692 try { | 679 try { |
| 693 mSensorManager.unregisterListener(listener, sensors.get(0)); | 680 mSensorManager.unregisterListener(listener, sensors.get(0)); |
| 694 } catch (IllegalArgumentException e) { | 681 } catch (IllegalArgumentException e) { |
| 695 // Suppress occasional exception on Digma iDxD* devices: | 682 // Suppress occasional exception on Digma iDxD* devices: |
| 696 // Receiver not registered: android.hardware.SystemSensorManager $1 | 683 // Receiver not registered: android.hardware.SystemSensorManager $1 |
| 697 // See crbug.com/596453. | 684 // See crbug.com/596453. |
| 698 Log.w(TAG, "Failed to unregister device sensor " + sensors.get(0 ).getName()); | 685 Log.w(TAG, "Failed to unregister device sensor " + sensors.get(0 ).getName()); |
| 699 } | 686 } |
| 700 } | 687 } |
| 701 } | 688 } |
| 702 | |
| 703 } | 689 } |
| OLD | NEW |