Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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.content.browser; |
| 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.Looper; | 13 import android.os.Looper; |
| 14 import android.util.Log; | |
| 15 | |
| 16 import com.google.common.annotations.VisibleForTesting; | |
| 17 import com.google.common.collect.ImmutableSet; | |
| 18 import com.google.common.collect.Sets; | |
| 14 | 19 |
| 15 import org.chromium.base.CalledByNative; | 20 import org.chromium.base.CalledByNative; |
| 16 import org.chromium.base.JNINamespace; | 21 import org.chromium.base.JNINamespace; |
| 17 import org.chromium.base.WeakContext; | 22 import org.chromium.base.WeakContext; |
| 18 | 23 |
| 19 import java.util.List; | 24 import java.util.List; |
| 25 import java.util.Set; | |
| 20 | 26 |
| 21 /** | 27 /** |
| 22 * Android implementation of the DeviceOrientation API. | 28 * Android implementation of the device motion and orientation APIs. |
| 23 */ | 29 */ |
| 24 @JNINamespace("content") | 30 @JNINamespace("content") |
| 25 class DeviceOrientation implements SensorEventListener { | 31 class DeviceMotionAndOrientation implements SensorEventListener { |
| 32 | |
| 33 private static final String LOGTAG = "DeviceMotionAndOrientation"; | |
|
bulach
2013/03/19 15:22:36
nit: normally this is just "TAG"
timvolodine
2013/03/19 16:50:08
Done.
| |
| 26 | 34 |
| 27 // These fields are lazily initialized by getHandler(). | 35 // These fields are lazily initialized by getHandler(). |
| 28 private Thread mThread; | 36 private Thread mThread; |
| 29 private Handler mHandler; | 37 private Handler mHandler; |
| 30 | 38 |
| 31 // The lock to access the mHandler. | 39 // The lock to access the mHandler. |
| 32 private Object mHandlerLock = new Object(); | 40 private Object mHandlerLock = new Object(); |
| 33 | 41 |
| 34 // Non-zero if and only if we're listening for events. | 42 // Non-zero if and only if we're listening for events. |
| 35 // To avoid race conditions on the C++ side, access must be synchronized. | 43 // To avoid race conditions on the C++ side, access must be synchronized. |
| 36 private int mNativePtr; | 44 private int mNativePtr; |
| 37 | 45 |
| 38 // The lock to access the mNativePtr. | 46 // The lock to access the mNativePtr. |
| 39 private Object mNativePtrLock = new Object(); | 47 private Object mNativePtrLock = new Object(); |
| 40 | 48 |
| 41 // The gravity vector expressed in the body frame. | 49 // The acceleration vector including gravity expressed in the body frame. |
| 42 private float[] mGravityVector; | 50 private float[] mAccelerationVector; |
| 43 | 51 |
| 44 // The geomagnetic vector expressed in the body frame. | 52 // The geomagnetic vector expressed in the body frame. |
| 45 private float[] mMagneticFieldVector; | 53 private float[] mMagneticFieldVector; |
| 46 | 54 |
| 47 // Lazily initialized when registering for notifications. | 55 // Lazily initialized when registering for notifications. |
| 48 private SensorManager mSensorManager; | 56 private SensorManagerProxy mSensorManagerProxy; |
| 49 | 57 |
| 50 // The only instance of that class and its associated lock. | 58 // The only instance of that class and its associated lock. |
| 51 private static DeviceOrientation sSingleton; | 59 private static DeviceMotionAndOrientation sSingleton; |
| 52 private static Object sSingletonLock = new Object(); | 60 private static Object sSingletonLock = new Object(); |
| 53 | 61 |
| 54 private DeviceOrientation() { | 62 /** |
| 63 * constants for using in JNI calls, also see | |
| 64 * content/browser/device_orientation/data_fetcher_impl_android.cc | |
| 65 */ | |
| 66 static final int DEVICE_ORIENTATION = 0; | |
| 67 static final int DEVICE_MOTION = 1; | |
| 68 | |
| 69 static ImmutableSet<Integer> DEVICE_ORIENTATION_SENSORS = ImmutableSet.of( | |
| 70 Sensor.TYPE_ACCELEROMETER, | |
| 71 Sensor.TYPE_MAGNETIC_FIELD); | |
| 72 | |
| 73 static ImmutableSet<Integer> DEVICE_MOTION_SENSORS = ImmutableSet.of( | |
| 74 Sensor.TYPE_ACCELEROMETER, | |
| 75 Sensor.TYPE_LINEAR_ACCELERATION, | |
| 76 Sensor.TYPE_GYROSCOPE); | |
| 77 | |
| 78 @VisibleForTesting | |
| 79 Set<Integer> mActiveSensors = Sets.newHashSet(); | |
|
bulach
2013/03/19 15:22:36
nit: final here, 69 and 73
timvolodine
2013/03/19 16:50:08
Done.
| |
| 80 boolean mDeviceMotionIsActive = false; | |
| 81 boolean mDeviceOrientationIsActive = false; | |
| 82 | |
| 83 protected DeviceMotionAndOrientation() { | |
| 55 } | 84 } |
| 56 | 85 |
| 57 /** | 86 /** |
| 58 * Start listening for sensor events. If this object is already listening | 87 * Start listening for sensor events. If this object is already listening |
| 59 * for events, the old callback is unregistered first. | 88 * for events, the old callback is unregistered first. |
| 60 * | 89 * |
| 61 * @param nativePtr Value to pass to nativeGotOrientation() for each event. | 90 * @param nativePtr Value to pass to nativeGotOrientation() for each event. |
| 62 * @param rateInMilliseconds Requested callback rate in milliseconds. The | 91 * @param rateInMilliseconds Requested callback rate in milliseconds. The |
| 63 * actual rate may be higher. Unwanted events should be ignored. | 92 * actual rate may be higher. Unwanted events should be ignored. |
| 93 * @param eventType Type of event to listen to, can be either DEVICE_ORIENTA TION or | |
| 94 * DEVICE_MOTION. | |
| 64 * @return True on success. | 95 * @return True on success. |
| 65 */ | 96 */ |
| 66 @CalledByNative | 97 @CalledByNative |
| 67 public boolean start(int nativePtr, int rateInMilliseconds) { | 98 public boolean start(int nativePtr, int eventType, int rateInMilliseconds) { |
| 99 boolean success = false; | |
| 68 synchronized (mNativePtrLock) { | 100 synchronized (mNativePtrLock) { |
| 69 stop(); | 101 switch (eventType) { |
| 70 if (registerForSensors(rateInMilliseconds)) { | 102 case DEVICE_ORIENTATION: |
| 103 success = registerSensors(DEVICE_ORIENTATION_SENSORS, rateIn Milliseconds, | |
| 104 true); | |
| 105 break; | |
| 106 case DEVICE_MOTION: | |
| 107 // note: device motion spec does not require all sensors to be available | |
| 108 success = registerSensors(DEVICE_MOTION_SENSORS, rateInMilli seconds, false); | |
| 109 break; | |
| 110 default: | |
| 111 Log.e(LOGTAG, "Unknown event type: " + eventType); | |
| 112 return false; | |
| 113 } | |
| 114 if (success) { | |
| 71 mNativePtr = nativePtr; | 115 mNativePtr = nativePtr; |
| 72 return true; | 116 setActiveEventType(eventType, true); |
| 73 } | 117 } |
| 74 return false; | 118 return success; |
| 75 } | 119 } |
| 76 } | 120 } |
| 77 | 121 |
| 78 /** | 122 /** |
| 79 * Stop listening for sensor events. Always succeeds. | 123 * Stop listening to sensors for a given event type. Ensures that sensors ar e not disabled |
| 124 * if they are still in use by a different event type. | |
| 80 * | 125 * |
| 81 * We strictly guarantee that nativeGotOrientation() will not be called | 126 * @param eventType Type of event to listen to, can be either DEVICE_ORIENTA TION or |
| 127 * DEVICE_MOTION. | |
| 128 * We strictly guarantee that the corresponding native*() methods will not b e called | |
| 82 * after this method returns. | 129 * after this method returns. |
| 83 */ | 130 */ |
| 84 @CalledByNative | 131 @CalledByNative |
| 85 public void stop() { | 132 public void stop(int eventType) { |
| 133 Set<Integer> sensorsToRemainActive = Sets.newHashSet(); | |
| 86 synchronized (mNativePtrLock) { | 134 synchronized (mNativePtrLock) { |
| 87 if (mNativePtr != 0) { | 135 switch (eventType) { |
| 88 mNativePtr = 0; | 136 case DEVICE_ORIENTATION: |
| 89 unregisterForSensors(); | 137 if (mDeviceMotionIsActive) { |
| 138 sensorsToRemainActive.addAll(DEVICE_MOTION_SENSORS); | |
| 139 } | |
| 140 break; | |
| 141 case DEVICE_MOTION: | |
| 142 if (mDeviceOrientationIsActive) { | |
| 143 sensorsToRemainActive.addAll(DEVICE_ORIENTATION_SENSORS) ; | |
| 144 } | |
| 145 break; | |
| 146 default: | |
| 147 Log.e(LOGTAG, "Unknown event type: " + eventType); | |
| 148 return; | |
| 90 } | 149 } |
| 150 | |
| 151 Set<Integer> sensorsToDeactivate = Sets.newHashSet(mActiveSensors); | |
| 152 sensorsToDeactivate.removeAll(sensorsToRemainActive); | |
| 153 unregisterSensors(sensorsToDeactivate); | |
| 154 mNativePtr = 0; | |
|
bulach
2013/03/19 15:22:36
shouldn't the native ptr only go away if there are
timvolodine
2013/03/19 16:50:08
Done.
| |
| 155 setActiveEventType(eventType, false); | |
| 91 } | 156 } |
| 92 } | 157 } |
| 93 | 158 |
| 94 @Override | 159 @Override |
| 95 public void onAccuracyChanged(Sensor sensor, int accuracy) { | 160 public void onAccuracyChanged(Sensor sensor, int accuracy) { |
| 96 // Nothing | 161 // Nothing |
| 97 } | 162 } |
| 98 | 163 |
| 99 @Override | 164 @Override |
| 100 public void onSensorChanged(SensorEvent event) { | 165 public void onSensorChanged(SensorEvent event) { |
| 101 switch (event.sensor.getType()) { | 166 sensorChanged(event.sensor.getType(), event.values); |
| 167 } | |
| 168 | |
| 169 @VisibleForTesting | |
| 170 void sensorChanged(int type, float[] values) { | |
| 171 | |
| 172 switch (type) { | |
| 102 case Sensor.TYPE_ACCELEROMETER: | 173 case Sensor.TYPE_ACCELEROMETER: |
| 103 if (mGravityVector == null) { | 174 if (mAccelerationVector == null) { |
| 104 mGravityVector = new float[3]; | 175 mAccelerationVector = new float[3]; |
| 105 } | 176 } |
| 106 System.arraycopy(event.values, 0, mGravityVector, 0, mGravityVec tor.length); | 177 System.arraycopy(values, 0, mAccelerationVector, 0, |
| 178 mAccelerationVector.length); | |
| 179 if (mDeviceMotionIsActive) { | |
| 180 gotAccelerationIncludingGravity(mAccelerationVector[0], mAcc elerationVector[1], | |
| 181 mAccelerationVector[2]); | |
| 182 } | |
| 107 break; | 183 break; |
| 108 | 184 case Sensor.TYPE_LINEAR_ACCELERATION: |
| 185 if (mDeviceMotionIsActive) { | |
| 186 gotAcceleration(values[0], values[1], values[2]); | |
| 187 } | |
| 188 break; | |
| 189 case Sensor.TYPE_GYROSCOPE: | |
| 190 if (mDeviceMotionIsActive) { | |
| 191 gotRotationRate(values[0], values[1], values[2]); | |
| 192 } | |
| 193 break; | |
| 109 case Sensor.TYPE_MAGNETIC_FIELD: | 194 case Sensor.TYPE_MAGNETIC_FIELD: |
| 110 if (mMagneticFieldVector == null) { | 195 if (mMagneticFieldVector == null) { |
| 111 mMagneticFieldVector = new float[3]; | 196 mMagneticFieldVector = new float[3]; |
| 112 } | 197 } |
| 113 System.arraycopy(event.values, 0, mMagneticFieldVector, 0, | 198 System.arraycopy(values, 0, mMagneticFieldVector, 0, |
| 114 mMagneticFieldVector.length); | 199 mMagneticFieldVector.length); |
| 115 break; | 200 break; |
| 116 | |
| 117 default: | 201 default: |
| 118 // Unexpected | 202 // Unexpected |
| 119 return; | 203 return; |
| 120 } | 204 } |
| 121 | 205 |
| 122 getOrientationUsingGetRotationMatrix(); | 206 if (mDeviceOrientationIsActive) { |
| 207 getOrientationUsingGetRotationMatrix(); | |
| 208 } | |
| 123 } | 209 } |
| 124 | 210 |
| 125 void getOrientationUsingGetRotationMatrix() { | 211 private void getOrientationUsingGetRotationMatrix() { |
| 126 if (mGravityVector == null || mMagneticFieldVector == null) { | 212 if (mAccelerationVector == null || mMagneticFieldVector == null) { |
| 127 return; | 213 return; |
| 128 } | 214 } |
| 129 | 215 |
| 130 // Get the rotation matrix. | 216 // Get the rotation matrix. |
| 131 // The rotation matrix that transforms from the body frame to the earth | 217 // The rotation matrix that transforms from the body frame to the earth |
| 132 // frame. | 218 // frame. |
| 133 float[] deviceRotationMatrix = new float[9]; | 219 float[] deviceRotationMatrix = new float[9]; |
| 134 if (!SensorManager.getRotationMatrix(deviceRotationMatrix, null, mGravit yVector, | 220 if (!SensorManager.getRotationMatrix(deviceRotationMatrix, null, mAccele rationVector, |
| 135 mMagneticFieldVector)) { | 221 mMagneticFieldVector)) { |
| 136 return; | 222 return; |
| 137 } | 223 } |
| 138 | 224 |
| 139 // Convert rotation matrix to rotation angles. | 225 // Convert rotation matrix to rotation angles. |
| 140 // Assuming that the rotations are appied in the order listed at | 226 // Assuming that the rotations are appied in the order listed at |
| 141 // http://developer.android.com/reference/android/hardware/SensorEvent.h tml#values | 227 // http://developer.android.com/reference/android/hardware/SensorEvent.h tml#values |
| 142 // the rotations are applied about the same axes and in the same order a s required by the | 228 // the rotations are applied about the same axes and in the same order a s required by the |
| 143 // API. The only conversions are sign changes as follows. The angles ar e in radians | 229 // API. The only conversions are sign changes as follows. The angles ar e in radians |
| 144 | 230 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 156 } | 242 } |
| 157 | 243 |
| 158 double gamma = Math.toDegrees(rotationAngles[2]); | 244 double gamma = Math.toDegrees(rotationAngles[2]); |
| 159 while (gamma < -90.0) { | 245 while (gamma < -90.0) { |
| 160 gamma += 360.0; // [-90, 90) | 246 gamma += 360.0; // [-90, 90) |
| 161 } | 247 } |
| 162 | 248 |
| 163 gotOrientation(alpha, beta, gamma); | 249 gotOrientation(alpha, beta, gamma); |
| 164 } | 250 } |
| 165 | 251 |
| 166 boolean registerForSensors(int rateInMilliseconds) { | 252 private SensorManagerProxy getSensorManagerProxy() { |
| 167 if (registerForSensorType(Sensor.TYPE_ACCELEROMETER, rateInMilliseconds) | 253 if (mSensorManagerProxy != null) { |
| 168 && registerForSensorType(Sensor.TYPE_MAGNETIC_FIELD, rateInMilli seconds)) { | 254 return mSensorManagerProxy; |
| 169 return true; | |
| 170 } | 255 } |
| 171 unregisterForSensors(); | 256 mSensorManagerProxy = new SensorManagerProxyImpl(); |
| 172 return false; | 257 return mSensorManagerProxy; |
| 173 } | 258 } |
| 174 | 259 |
| 175 private SensorManager getSensorManager() { | 260 @VisibleForTesting |
| 176 if (mSensorManager != null) { | 261 void setSensorManagerProxy(SensorManagerProxy sensorManager) { |
| 177 return mSensorManager; | 262 mSensorManagerProxy = sensorManager; |
| 178 } | |
| 179 mSensorManager = (SensorManager)WeakContext.getSystemService(Context.SEN SOR_SERVICE); | |
| 180 return mSensorManager; | |
| 181 } | 263 } |
| 182 | 264 |
| 183 void unregisterForSensors() { | 265 private void setActiveEventType(int eventType, boolean value) { |
|
bulach
2013/03/19 15:22:36
nit: this would read better as "setEventTypeActive
timvolodine
2013/03/19 16:50:08
Done.
| |
| 184 SensorManager sensorManager = getSensorManager(); | 266 switch (eventType) { |
| 185 if (sensorManager == null) { | 267 case DEVICE_ORIENTATION: |
| 186 return; | 268 mDeviceOrientationIsActive = value; |
| 269 return; | |
| 270 case DEVICE_MOTION: | |
| 271 mDeviceMotionIsActive = value; | |
| 272 return; | |
| 187 } | 273 } |
| 188 sensorManager.unregisterListener(this); | 274 } |
| 275 | |
| 276 /** | |
| 277 * @param sensorTypes List of sensors to activate. | |
| 278 * @param rateInMilliseconds Intented delay (in milliseconds) between sensor readings. | |
| 279 * @param failOnMissingSensor If true the method returns true only if all se nsors could be | |
| 280 * activated. When false the method return true i f at least one | |
| 281 * sensor in sensorTypes could be activated. | |
| 282 */ | |
| 283 private boolean registerSensors(Iterable<Integer> sensorTypes, int rateInMil liseconds, | |
| 284 boolean failOnMissingSensor) { | |
|
bulach
2013/03/19 15:22:36
nit: alignment
timvolodine
2013/03/19 16:50:08
Done.
| |
| 285 Set<Integer> sensorsToActivate = Sets.newHashSet(sensorTypes); | |
| 286 sensorsToActivate.removeAll(mActiveSensors); | |
| 287 boolean success = false; | |
| 288 | |
| 289 for (Integer sensorType : sensorsToActivate) { | |
| 290 boolean result = registerForSensorType(sensorType, rateInMillisecond s); | |
| 291 if (!result && failOnMissingSensor) { | |
| 292 // restore the previous state upon failure | |
| 293 unregisterSensors(sensorsToActivate); | |
| 294 return false; | |
| 295 } | |
| 296 if (result) { | |
| 297 mActiveSensors.add(sensorType); | |
| 298 success = true; | |
| 299 } | |
| 300 } | |
| 301 return success; | |
| 302 } | |
| 303 | |
| 304 private void unregisterSensors(Iterable<Integer> sensorTypes) { | |
| 305 for (Integer sensorType : sensorTypes) { | |
| 306 if (mActiveSensors.contains(sensorType)) { | |
| 307 List<Sensor> sensors = getSensorManagerProxy().getSensorList(sen sorType); | |
|
bulach
2013/03/19 15:22:36
all usages of getSensorList() check for empty and
timvolodine
2013/03/19 16:50:08
nice point, simplifies the code indeed -- done!
O
| |
| 308 if (!sensors.isEmpty()) { | |
| 309 getSensorManagerProxy().unregisterListener(this, sensors.get (0)); | |
| 310 mActiveSensors.remove(sensorType); | |
| 311 } | |
| 312 } | |
| 313 } | |
| 189 } | 314 } |
| 190 | 315 |
| 191 boolean registerForSensorType(int type, int rateInMilliseconds) { | 316 boolean registerForSensorType(int type, int rateInMilliseconds) { |
| 192 SensorManager sensorManager = getSensorManager(); | 317 SensorManagerProxy sensorManager = getSensorManagerProxy(); |
| 193 if (sensorManager == null) { | 318 if (sensorManager == null) { |
| 194 return false; | 319 return false; |
| 195 } | 320 } |
| 196 List<Sensor> sensors = sensorManager.getSensorList(type); | 321 List<Sensor> sensors = sensorManager.getSensorList(type); |
| 197 if (sensors.isEmpty()) { | 322 if (sensors.isEmpty()) { |
| 198 return false; | 323 return false; |
| 199 } | 324 } |
| 200 | 325 |
| 201 final int rateInMicroseconds = 1000 * rateInMilliseconds; | 326 final int rateInMicroseconds = 1000 * rateInMilliseconds; |
| 202 // We want to err on the side of getting more events than we need. | 327 return sensorManager.registerListener(this, sensors.get(0), rateInMicros econds, |
| 203 final int requestedRate = rateInMicroseconds / 2; | 328 getHandler()); |
| 204 | |
| 205 // TODO(steveblock): Consider handling multiple sensors. | |
| 206 return sensorManager.registerListener(this, sensors.get(0), requestedRat e, getHandler()); | |
| 207 } | 329 } |
| 208 | 330 |
| 209 void gotOrientation(double alpha, double beta, double gamma) { | 331 protected void gotOrientation(double alpha, double beta, double gamma) { |
| 210 synchronized (mNativePtrLock) { | 332 synchronized (mNativePtrLock) { |
| 211 if (mNativePtr != 0) { | 333 if (mNativePtr != 0) { |
| 212 nativeGotOrientation(mNativePtr, alpha, beta, gamma); | 334 nativeGotOrientation(mNativePtr, alpha, beta, gamma); |
| 213 } | 335 } |
| 214 } | 336 } |
| 215 } | 337 } |
| 216 | 338 |
| 339 protected void gotAcceleration(double x, double y, double z) { | |
| 340 synchronized (mNativePtrLock) { | |
| 341 if (mNativePtr != 0) { | |
| 342 nativeGotAcceleration(mNativePtr, x, y, z); | |
| 343 } | |
| 344 } | |
| 345 } | |
| 346 | |
| 347 protected void gotAccelerationIncludingGravity(double x, double y, double z) { | |
| 348 synchronized (mNativePtrLock) { | |
| 349 if (mNativePtr != 0) { | |
| 350 nativeGotAccelerationIncludingGravity(mNativePtr, x, y, z); | |
| 351 } | |
| 352 } | |
| 353 } | |
| 354 | |
| 355 protected void gotRotationRate(double alpha, double beta, double gamma) { | |
| 356 synchronized (mNativePtrLock) { | |
| 357 if (mNativePtr != 0) { | |
| 358 nativeGotRotationRate(mNativePtr, alpha, beta, gamma); | |
| 359 } | |
| 360 } | |
| 361 } | |
| 362 | |
| 217 private Handler getHandler() { | 363 private Handler getHandler() { |
| 218 synchronized (mHandlerLock) { | 364 synchronized (mHandlerLock) { |
| 219 // If we don't have a background thread, start it now. | 365 // If we don't have a background thread, start it now. |
| 220 if (mThread == null) { | 366 if (mThread == null) { |
| 221 mThread = new Thread(new Runnable() { | 367 mThread = new Thread(new Runnable() { |
| 222 @Override | 368 @Override |
| 223 public void run() { | 369 public void run() { |
| 224 Looper.prepare(); | 370 Looper.prepare(); |
| 225 // Our Handler doesn't actually have to do anything, bec ause | 371 // Our Handler doesn't actually have to do anything, bec ause |
| 226 // SensorManager posts directly to the underlying Looper . | 372 // SensorManager posts directly to the underlying Looper . |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 244 } | 390 } |
| 245 | 391 |
| 246 private void setHandler(Handler handler) { | 392 private void setHandler(Handler handler) { |
| 247 synchronized (mHandlerLock) { | 393 synchronized (mHandlerLock) { |
| 248 mHandler = handler; | 394 mHandler = handler; |
| 249 mHandlerLock.notify(); | 395 mHandlerLock.notify(); |
| 250 } | 396 } |
| 251 } | 397 } |
| 252 | 398 |
| 253 @CalledByNative | 399 @CalledByNative |
| 254 private static DeviceOrientation getInstance() { | 400 static DeviceMotionAndOrientation getInstance() { |
| 255 synchronized (sSingletonLock) { | 401 synchronized (sSingletonLock) { |
| 256 if (sSingleton == null) { | 402 if (sSingleton == null) { |
| 257 sSingleton = new DeviceOrientation(); | 403 sSingleton = new DeviceMotionAndOrientation(); |
| 258 } | 404 } |
| 259 return sSingleton; | 405 return sSingleton; |
| 260 } | 406 } |
| 261 } | 407 } |
| 262 | 408 |
| 263 /** | 409 /** |
| 264 * See chrome/browser/device_orientation/data_fetcher_impl_android.cc | 410 * Native JNI calls, |
| 411 * see content/browser/device_orientation/data_fetcher_impl_android.cc | |
| 412 */ | |
| 413 | |
| 414 /** | |
| 415 * Orientation of the device with respect to its reference frame. | |
| 265 */ | 416 */ |
| 266 private native void nativeGotOrientation( | 417 private native void nativeGotOrientation( |
| 267 int nativeDataFetcherImplAndroid, | 418 int nativeDataFetcherImplAndroid, |
| 268 double alpha, double beta, double gamma); | 419 double alpha, double beta, double gamma); |
| 269 } | 420 |
| 421 /** | |
| 422 * Linear acceleration without gravity of the device with respect to its bod y frame. | |
| 423 */ | |
| 424 private native void nativeGotAcceleration( | |
| 425 int nativeDataFetcherImplAndroid, | |
| 426 double x, double y, double z); | |
| 427 | |
| 428 /** | |
| 429 * Acceleration including gravity of the device with respect to its body fra me. | |
| 430 */ | |
| 431 private native void nativeGotAccelerationIncludingGravity( | |
| 432 int nativeDataFetcherImplAndroid, | |
| 433 double x, double y, double z); | |
| 434 | |
| 435 /** | |
| 436 * Rotation rate of the device with respect to its body frame. | |
| 437 */ | |
| 438 private native void nativeGotRotationRate( | |
| 439 int nativeDataFetcherImplAndroid, | |
| 440 double alpha, double beta, double gamma); | |
| 441 | |
| 442 /** | |
| 443 * Need the an interface for SensorManager for testing. | |
| 444 */ | |
| 445 interface SensorManagerProxy { | |
| 446 public List<Sensor> getSensorList(int type); | |
|
bulach
2013/03/19 15:22:36
see above, I think this can be moved out of the in
timvolodine
2013/03/19 16:50:08
Done.
| |
| 447 public boolean registerListener(SensorEventListener listener, Sensor sen sor, int rate, | |
| 448 Handler handler); | |
| 449 public void unregisterListener(SensorEventListener listener, Sensor sens or); | |
| 450 } | |
| 451 | |
| 452 static class SensorManagerProxyImpl implements SensorManagerProxy { | |
| 453 private SensorManager mSensorManager; | |
| 454 | |
| 455 SensorManagerProxyImpl() { | |
| 456 mSensorManager = (SensorManager)WeakContext.getSystemService(Context .SENSOR_SERVICE); | |
| 457 } | |
| 458 | |
| 459 public List<Sensor> getSensorList(int type) { | |
| 460 return mSensorManager.getSensorList(type); | |
| 461 } | |
| 462 | |
| 463 public boolean registerListener(SensorEventListener listener, Sensor sen sor, int rate, | |
| 464 Handler handler) { | |
| 465 return mSensorManager.registerListener(listener, sensor, rate, handl er); | |
| 466 } | |
| 467 | |
| 468 public void unregisterListener(SensorEventListener listener, Sensor sens or) { | |
| 469 mSensorManager.unregisterListener(listener, sensor); | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 } | |
| OLD | NEW |