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.
5 package org.chromium.content.browser;
7 import android.content.Context;
8 import android.hardware.Sensor;
9 import android.hardware.SensorEventListener;
10 import android.hardware.SensorManager;
11 import android.os.Handler;
12 import android.test.AndroidTestCase;
13 import android.test.suitebuilder.annotation.SmallTest;
15 import java.util.HashSet;
19 * Test suite for DeviceSensors.
21 public class DeviceSensorsTest extends AndroidTestCase {
23 private DeviceSensorsForTests mDeviceSensors;
24 private MockSensorManager mMockSensorManager;
27 public void setUp() throws Exception {
29 mMockSensorManager = new MockSensorManager();
30 mDeviceSensors = DeviceSensorsForTests.getInstance(getContext());
31 mDeviceSensors.setSensorManagerProxy(mMockSensorManager);
35 public void testRegisterSensorsDeviceMotion() {
36 boolean start = mDeviceSensors.start(0,
37 DeviceSensors.DEVICE_MOTION, 100);
40 assertTrue("should contain all motion sensors",
41 mDeviceSensors.mActiveSensors.containsAll(
42 DeviceSensors.DEVICE_MOTION_SENSORS));
43 assertTrue(mDeviceSensors.mDeviceMotionIsActive);
44 assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
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());
54 public void testRegisterSensorsDeviceOrientation() {
55 boolean start = mDeviceSensors.start(0,
56 DeviceSensors.DEVICE_ORIENTATION, 100);
59 assertTrue("should contain all orientation sensors",
60 mDeviceSensors.mActiveSensors.containsAll(
61 DeviceSensors.DEVICE_ORIENTATION_SENSORS));
62 assertFalse(mDeviceSensors.mDeviceMotionIsActive);
63 assertTrue(mDeviceSensors.mDeviceOrientationIsActive);
65 assertEquals(DeviceSensors.DEVICE_ORIENTATION_SENSORS.size(),
66 mMockSensorManager.numRegistered);
67 assertEquals(0, mMockSensorManager.numUnRegistered);
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);
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));
86 Set<Integer> union = new HashSet<Integer>(
87 DeviceSensors.DEVICE_ORIENTATION_SENSORS);
88 union.addAll(DeviceSensors.DEVICE_MOTION_SENSORS);
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());
100 public void testUnregisterSensorsDeviceMotion() {
101 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100);
102 mDeviceSensors.stop(DeviceSensors.DEVICE_MOTION);
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());
114 public void testUnregisterSensorsDeviceOrientation() {
115 mDeviceSensors.start(0, DeviceSensors.DEVICE_ORIENTATION, 100);
116 mDeviceSensors.stop(DeviceSensors.DEVICE_ORIENTATION);
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);
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);
132 assertTrue("should contain all orientation sensors",
133 mDeviceSensors.mActiveSensors.containsAll(
134 DeviceSensors.DEVICE_ORIENTATION_SENSORS));
136 Set<Integer> diff = new HashSet<Integer>(DeviceSensors.DEVICE_MOTION_SENSORS);
137 diff.removeAll(DeviceSensors.DEVICE_ORIENTATION_SENSORS);
139 assertEquals(diff.size(), mMockSensorManager.numUnRegistered);
141 mDeviceSensors.stop(DeviceSensors.DEVICE_ORIENTATION);
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());
151 public void testSensorChangedgotOrientation() {
152 boolean startOrientation = mDeviceSensors.start(0,
153 DeviceSensors.DEVICE_ORIENTATION, 100);
155 assertTrue(startOrientation);
156 assertTrue(mDeviceSensors.mDeviceOrientationIsActive);
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);
166 public void testSensorChangedgotAccelerationIncludingGravity() {
167 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100);
169 float[] values = {1, 2, 3};
170 mDeviceSensors.sensorChanged(Sensor.TYPE_ACCELEROMETER, values);
171 mDeviceSensors.verifyCalls("gotAccelerationIncludingGravity");
172 mDeviceSensors.verifyValues(1, 2, 3);
176 public void testSensorChangedgotAcceleration() {
177 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100);
179 float[] values = {1, 2, 3};
180 mDeviceSensors.sensorChanged(Sensor.TYPE_LINEAR_ACCELERATION, values);
181 mDeviceSensors.verifyCalls("gotAcceleration");
182 mDeviceSensors.verifyValues(1, 2, 3);
186 public void testSensorChangedgotRotationRate() {
187 mDeviceSensors.start(0, DeviceSensors.DEVICE_MOTION, 100);
189 float[] values = {1, 2, 3};
190 mDeviceSensors.sensorChanged(Sensor.TYPE_GYROSCOPE, values);
191 mDeviceSensors.verifyCalls("gotRotationRate");
192 mDeviceSensors.verifyValues(1, 2, 3);
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);
202 assertTrue(startOrientation);
203 assertTrue(startMotion);
204 assertTrue(mDeviceSensors.mDeviceMotionIsActive);
205 assertTrue(mDeviceSensors.mDeviceOrientationIsActive);
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);
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);
221 // Tests for correct Device Orientation angles.
224 public void testOrientationAnglesFromRotationMatrixIdentity() {
225 float[] gravity = {0, 0, 1};
226 float[] magnetic = {0, 1, 0};
227 double[] expectedAngles = {0, 0, 0};
229 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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};
238 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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};
247 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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};
256 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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
265 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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};
276 verifyOrientationAngles(gravity, magnetic, expectedAngles);
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};
285 verifyOrientationAngles(gravity, magnetic, expectedAngles);
289 * Helper method for verifying angles obtained from rotation matrix.
292 * gravity vector in the device frame
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
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);
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);
315 // -- End Tests for correct Device Orientation angles.
317 private static class DeviceSensorsForTests extends DeviceSensors {
319 private double value1 = 0;
320 private double value2 = 0;
321 private double value3 = 0;
322 private String mCalls = "";
324 private DeviceSensorsForTests(Context context) {
328 static DeviceSensorsForTests getInstance(Context context) {
329 return new DeviceSensorsForTests(context);
332 private void verifyValues(double v1, double v2, double v3) {
333 assertEquals(v1, value1);
334 assertEquals(v2, value2);
335 assertEquals(v3, value3);
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);
344 private void verifyCalls(String names) {
345 assertEquals(mCalls, names);
349 protected void gotOrientation(double alpha, double beta, double gamma) {
353 mCalls = mCalls.concat("gotOrientation");
357 protected void gotAcceleration(double x, double y, double z) {
361 mCalls = mCalls.concat("gotAcceleration");
365 protected void gotAccelerationIncludingGravity(double x, double y, double z) {
369 mCalls = mCalls.concat("gotAccelerationIncludingGravity");
373 protected void gotRotationRate(double alpha, double beta, double gamma) {
377 mCalls = mCalls.concat("gotRotationRate");
381 private static class MockSensorManager implements
382 DeviceSensors.SensorManagerProxy {
384 private int numRegistered = 0;
385 private int numUnRegistered = 0;
387 private MockSensorManager() {
391 public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
398 public void unregisterListener(SensorEventListener listener, int sensorType) {