DeviceSensorsTest.java revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.content.browser; 6 7import android.content.Context; 8import android.hardware.Sensor; 9import android.hardware.SensorEventListener; 10import android.hardware.SensorManager; 11import android.os.Handler; 12import android.test.AndroidTestCase; 13import android.test.suitebuilder.annotation.SmallTest; 14 15import java.util.HashSet; 16import java.util.Set; 17 18/** 19 * Test suite for DeviceSensors. 20 */ 21public class DeviceSensorsTest extends AndroidTestCase { 22 23 private DeviceSensorsForTests mDeviceSensors; 24 private MockSensorManager mMockSensorManager; 25 26 @Override 27 public void setUp() throws Exception { 28 super.setUp(); 29 mMockSensorManager = new MockSensorManager(); 30 mDeviceSensors = DeviceSensorsForTests.getInstance(getContext()); 31 mDeviceSensors.setSensorManagerProxy(mMockSensorManager); 32 } 33 34 @SmallTest 35 public void testRegisterSensorsDeviceMotion() { 36 boolean start = mDeviceSensors.start(0, 37 DeviceSensors.DEVICE_MOTION, 100); 38 39 assertTrue(start); 40 assertTrue("should contain all motion sensors", 41 mDeviceSensors.mActiveSensors.containsAll( 42 DeviceSensors.DEVICE_MOTION_SENSORS)); 43 assertTrue(mDeviceSensors.mDeviceMotionIsActive); 44 assertFalse(mDeviceSensors.mDeviceOrientationIsActive); 45 46 assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(), 47 mMockSensorManager.numRegistered); 48 assertEquals(0, mMockSensorManager.numUnRegistered); 49 assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(), 50 mDeviceSensors.getNumberActiveDeviceMotionSensors()); 51 } 52 53 @SmallTest 54 public void testRegisterSensorsDeviceOrientation() { 55 boolean start = mDeviceSensors.start(0, 56 DeviceSensors.DEVICE_ORIENTATION, 100); 57 58 assertTrue(start); 59 assertTrue("should contain all orientation sensors", 60 mDeviceSensors.mActiveSensors.containsAll( 61 DeviceSensors.DEVICE_ORIENTATION_SENSORS)); 62 assertFalse(mDeviceSensors.mDeviceMotionIsActive); 63 assertTrue(mDeviceSensors.mDeviceOrientationIsActive); 64 65 assertEquals(DeviceSensors.DEVICE_ORIENTATION_SENSORS.size(), 66 mMockSensorManager.numRegistered); 67 assertEquals(0, mMockSensorManager.numUnRegistered); 68 } 69 70 @SmallTest 71 public void testRegisterSensorsDeviceMotionAndOrientation() { 72 boolean startOrientation = mDeviceSensors.start(0, 73 DeviceSensors.DEVICE_ORIENTATION, 100); 74 boolean startMotion = mDeviceSensors.start(0, 75 DeviceSensors.DEVICE_MOTION, 100); 76 77 assertTrue(startOrientation); 78 assertTrue(startMotion); 79 assertTrue("should contain all motion sensors", 80 mDeviceSensors.mActiveSensors.containsAll( 81 DeviceSensors.DEVICE_MOTION_SENSORS)); 82 assertTrue("should contain all orientation sensors", 83 mDeviceSensors.mActiveSensors.containsAll( 84 DeviceSensors.DEVICE_ORIENTATION_SENSORS)); 85 86 Set<Integer> union = new HashSet<Integer>( 87 DeviceSensors.DEVICE_ORIENTATION_SENSORS); 88 union.addAll(DeviceSensors.DEVICE_MOTION_SENSORS); 89 90 assertEquals(union.size(), mDeviceSensors.mActiveSensors.size()); 91 assertTrue(mDeviceSensors.mDeviceMotionIsActive); 92 assertTrue(mDeviceSensors.mDeviceOrientationIsActive); 93 assertEquals(union.size(), mMockSensorManager.numRegistered); 94 assertEquals(0, mMockSensorManager.numUnRegistered); 95 assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(), 96 mDeviceSensors.getNumberActiveDeviceMotionSensors()); 97 } 98 99 @SmallTest 100 public void testUnregisterSensorsDeviceMotion() { 101 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100); 102 mDeviceSensors.stop(DeviceSensors.DEVICE_MOTION); 103 104 assertTrue("should contain no sensors", 105 mDeviceSensors.mActiveSensors.isEmpty()); 106 assertFalse(mDeviceSensors.mDeviceMotionIsActive); 107 assertFalse(mDeviceSensors.mDeviceOrientationIsActive); 108 assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(), 109 mMockSensorManager.numUnRegistered); 110 assertEquals(0, mDeviceSensors.getNumberActiveDeviceMotionSensors()); 111 } 112 113 @SmallTest 114 public void testUnregisterSensorsDeviceOrientation() { 115 mDeviceSensors.start(0, DeviceSensors.DEVICE_ORIENTATION, 100); 116 mDeviceSensors.stop(DeviceSensors.DEVICE_ORIENTATION); 117 118 assertTrue("should contain no sensors", 119 mDeviceSensors.mActiveSensors.isEmpty()); 120 assertFalse(mDeviceSensors.mDeviceMotionIsActive); 121 assertFalse(mDeviceSensors.mDeviceOrientationIsActive); 122 assertEquals(DeviceSensors.DEVICE_ORIENTATION_SENSORS.size(), 123 mMockSensorManager.numUnRegistered); 124 } 125 126 @SmallTest 127 public void testUnRegisterSensorsDeviceMotionAndOrientation() { 128 mDeviceSensors.start(0, DeviceSensors.DEVICE_ORIENTATION, 100); 129 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100); 130 mDeviceSensors.stop(DeviceSensors.DEVICE_MOTION); 131 132 assertTrue("should contain all orientation sensors", 133 mDeviceSensors.mActiveSensors.containsAll( 134 DeviceSensors.DEVICE_ORIENTATION_SENSORS)); 135 136 Set<Integer> diff = new HashSet<Integer>(DeviceSensors.DEVICE_MOTION_SENSORS); 137 diff.removeAll(DeviceSensors.DEVICE_ORIENTATION_SENSORS); 138 139 assertEquals(diff.size(), mMockSensorManager.numUnRegistered); 140 141 mDeviceSensors.stop(DeviceSensors.DEVICE_ORIENTATION); 142 143 assertTrue("should contain no sensors", 144 mDeviceSensors.mActiveSensors.isEmpty()); 145 assertEquals(diff.size() + DeviceSensors.DEVICE_ORIENTATION_SENSORS.size(), 146 mMockSensorManager.numUnRegistered); 147 assertEquals(0, mDeviceSensors.getNumberActiveDeviceMotionSensors()); 148 } 149 150 @SmallTest 151 public void testSensorChangedgotOrientation() { 152 boolean startOrientation = mDeviceSensors.start(0, 153 DeviceSensors.DEVICE_ORIENTATION, 100); 154 155 assertTrue(startOrientation); 156 assertTrue(mDeviceSensors.mDeviceOrientationIsActive); 157 158 float alpha = (float) Math.PI / 4; 159 float[] values = {0, 0, (float) Math.sin(alpha / 2), (float) Math.cos(alpha / 2), -1}; 160 mDeviceSensors.sensorChanged(Sensor.TYPE_ROTATION_VECTOR, values); 161 mDeviceSensors.verifyCalls("gotOrientation"); 162 mDeviceSensors.verifyValuesEpsilon(Math.toDegrees(alpha), 0, 0); 163 } 164 165 @SmallTest 166 public void testSensorChangedgotAccelerationIncludingGravity() { 167 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100); 168 169 float[] values = {1, 2, 3}; 170 mDeviceSensors.sensorChanged(Sensor.TYPE_ACCELEROMETER, values); 171 mDeviceSensors.verifyCalls("gotAccelerationIncludingGravity"); 172 mDeviceSensors.verifyValues(1, 2, 3); 173 } 174 175 @SmallTest 176 public void testSensorChangedgotAcceleration() { 177 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100); 178 179 float[] values = {1, 2, 3}; 180 mDeviceSensors.sensorChanged(Sensor.TYPE_LINEAR_ACCELERATION, values); 181 mDeviceSensors.verifyCalls("gotAcceleration"); 182 mDeviceSensors.verifyValues(1, 2, 3); 183 } 184 185 @SmallTest 186 public void testSensorChangedgotRotationRate() { 187 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100); 188 189 float[] values = {1, 2, 3}; 190 mDeviceSensors.sensorChanged(Sensor.TYPE_GYROSCOPE, values); 191 mDeviceSensors.verifyCalls("gotRotationRate"); 192 mDeviceSensors.verifyValues(1, 2, 3); 193 } 194 195 @SmallTest 196 public void testSensorChangedgotOrientationAndAcceleration() { 197 boolean startOrientation = mDeviceSensors.start(0, 198 DeviceSensors.DEVICE_ORIENTATION, 100); 199 boolean startMotion = mDeviceSensors.start(0, 200 DeviceSensors.DEVICE_MOTION, 100); 201 202 assertTrue(startOrientation); 203 assertTrue(startMotion); 204 assertTrue(mDeviceSensors.mDeviceMotionIsActive); 205 assertTrue(mDeviceSensors.mDeviceOrientationIsActive); 206 207 float alpha = (float) Math.PI / 4; 208 float[] values = {0, 0, (float) Math.sin(alpha / 2), (float) Math.cos(alpha / 2), -1}; 209 mDeviceSensors.sensorChanged(Sensor.TYPE_ROTATION_VECTOR, values); 210 mDeviceSensors.verifyCalls("gotOrientation"); 211 mDeviceSensors.verifyValuesEpsilon(Math.toDegrees(alpha), 0, 0); 212 213 float[] values2 = {1, 2, 3}; 214 mDeviceSensors.sensorChanged(Sensor.TYPE_ACCELEROMETER, values2); 215 mDeviceSensors.verifyCalls("gotOrientation" + 216 "gotAccelerationIncludingGravity"); 217 mDeviceSensors.verifyValues(1, 2, 3); 218 } 219 220 221 // Tests for correct Device Orientation angles. 222 223 @SmallTest 224 public void testOrientationAnglesFromRotationMatrixIdentity() { 225 float[] gravity = {0, 0, 1}; 226 float[] magnetic = {0, 1, 0}; 227 double[] expectedAngles = {0, 0, 0}; 228 229 verifyOrientationAngles(gravity, magnetic, expectedAngles); 230 } 231 232 @SmallTest 233 public void testOrientationAnglesFromRotationMatrix45DegreesX() { 234 float[] gravity = {0, (float) Math.sin(Math.PI / 4), (float) Math.cos(Math.PI / 4)}; 235 float[] magnetic = {0, 1, 0}; 236 double[] expectedAngles = {0, Math.PI / 4, 0}; 237 238 verifyOrientationAngles(gravity, magnetic, expectedAngles); 239 } 240 241 @SmallTest 242 public void testOrientationAnglesFromRotationMatrix45DegreesY() { 243 float[] gravity = {-(float) Math.sin(Math.PI / 4), 0, (float) Math.cos(Math.PI / 4)}; 244 float[] magnetic = {0, 1, 0}; 245 double[] expectedAngles = {0, 0, Math.PI / 4}; 246 247 verifyOrientationAngles(gravity, magnetic, expectedAngles); 248 } 249 250 @SmallTest 251 public void testOrientationAnglesFromRotationMatrix45DegreesZ() { 252 float[] gravity = {0, 0, 1}; 253 float[] magnetic = {(float) Math.sin(Math.PI / 4), (float) Math.cos(Math.PI / 4), 0}; 254 double[] expectedAngles = {Math.PI / 4, 0, 0}; 255 256 verifyOrientationAngles(gravity, magnetic, expectedAngles); 257 } 258 259 @SmallTest 260 public void testOrientationAnglesFromRotationMatrixGimbalLock() { 261 float[] gravity = {0, 1, 0}; 262 float[] magnetic = {(float) Math.sin(Math.PI / 4), 0, -(float) Math.cos(Math.PI / 4)}; 263 double[] expectedAngles = {Math.PI / 4, Math.PI / 2, 0}; // favor yaw instead of roll 264 265 verifyOrientationAngles(gravity, magnetic, expectedAngles); 266 } 267 268 @SmallTest 269 public void testOrientationAnglesFromRotationMatrixPitchGreaterThan90() { 270 final double largePitchAngle = Math.PI / 2 + Math.PI / 4; 271 float[] gravity = {0, (float) Math.cos(largePitchAngle - Math.PI / 2), 272 -(float) Math.sin(largePitchAngle - Math.PI / 2)}; 273 float[] magnetic = {0, 0, -1}; 274 double[] expectedAngles = {0, largePitchAngle, 0}; 275 276 verifyOrientationAngles(gravity, magnetic, expectedAngles); 277 } 278 279 @SmallTest 280 public void testOrientationAnglesFromRotationMatrixRoll90() { 281 float[] gravity = {-1, 0, 0}; 282 float[] magnetic = {0, 1, 0}; 283 double[] expectedAngles = {Math.PI, -Math.PI, -Math.PI / 2}; 284 285 verifyOrientationAngles(gravity, magnetic, expectedAngles); 286 } 287 288 /** 289 * Helper method for verifying angles obtained from rotation matrix. 290 * 291 * @param gravity 292 * gravity vector in the device frame 293 * @param magnetic 294 * magnetic field vector in the device frame 295 * @param expectedAngles 296 * expectedAngles[0] rotation angle in radians around the Z-axis 297 * expectedAngles[1] rotation angle in radians around the X-axis 298 * expectedAngles[2] rotation angle in radians around the Y-axis 299 */ 300 private void verifyOrientationAngles(float[] gravity, float[] magnetic, 301 double[] expectedAngles) { 302 float[] R = new float[9]; 303 double[] values = new double[3]; 304 SensorManager.getRotationMatrix(R, null, gravity, magnetic); 305 mDeviceSensors.computeDeviceOrientationFromRotationMatrix(R, values); 306 307 assertEquals(expectedAngles.length, values.length); 308 final double epsilon = 0.001; 309 for (int i = 0; i < expectedAngles.length; ++i) { 310 assertEquals(expectedAngles[i], values[i], epsilon); 311 } 312 313 } 314 315 // -- End Tests for correct Device Orientation angles. 316 317 private static class DeviceSensorsForTests extends DeviceSensors { 318 319 private double value1 = 0; 320 private double value2 = 0; 321 private double value3 = 0; 322 private String mCalls = ""; 323 324 private DeviceSensorsForTests(Context context) { 325 super(context); 326 } 327 328 static DeviceSensorsForTests getInstance(Context context) { 329 return new DeviceSensorsForTests(context); 330 } 331 332 private void verifyValues(double v1, double v2, double v3) { 333 assertEquals(v1, value1); 334 assertEquals(v2, value2); 335 assertEquals(v3, value3); 336 } 337 338 private void verifyValuesEpsilon(double v1, double v2, double v3) { 339 assertEquals(v1, value1, 0.1); 340 assertEquals(v2, value2, 0.1); 341 assertEquals(v3, value3, 0.1); 342 } 343 344 private void verifyCalls(String names) { 345 assertEquals(mCalls, names); 346 } 347 348 @Override 349 protected void gotOrientation(double alpha, double beta, double gamma) { 350 value1 = alpha; 351 value2 = beta; 352 value3 = gamma; 353 mCalls = mCalls.concat("gotOrientation"); 354 } 355 356 @Override 357 protected void gotAcceleration(double x, double y, double z) { 358 value1 = x; 359 value2 = y; 360 value3 = z; 361 mCalls = mCalls.concat("gotAcceleration"); 362 } 363 364 @Override 365 protected void gotAccelerationIncludingGravity(double x, double y, double z) { 366 value1 = x; 367 value2 = y; 368 value3 = z; 369 mCalls = mCalls.concat("gotAccelerationIncludingGravity"); 370 } 371 372 @Override 373 protected void gotRotationRate(double alpha, double beta, double gamma) { 374 value1 = alpha; 375 value2 = beta; 376 value3 = gamma; 377 mCalls = mCalls.concat("gotRotationRate"); 378 } 379 } 380 381 private static class MockSensorManager implements 382 DeviceSensors.SensorManagerProxy { 383 384 private int numRegistered = 0; 385 private int numUnRegistered = 0; 386 387 private MockSensorManager() { 388 } 389 390 @Override 391 public boolean registerListener(SensorEventListener listener, int sensorType, int rate, 392 Handler handler) { 393 numRegistered++; 394 return true; 395 } 396 397 @Override 398 public void unregisterListener(SensorEventListener listener, int sensorType) { 399 numUnRegistered++; 400 } 401 } 402} 403