1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.hardware.cts; 17 18 import android.content.Context; 19 import android.hardware.Sensor; 20 import android.hardware.SensorManager; 21 import android.hardware.cts.helpers.SensorCtsHelper; 22 import android.hardware.cts.helpers.TestSensorEnvironment; 23 import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation; 24 import android.hardware.cts.helpers.sensoroperations.RepeatingSensorOperation; 25 import android.hardware.cts.helpers.sensoroperations.SequentialSensorOperation; 26 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation; 27 import android.hardware.cts.helpers.sensorverification.EventOrderingVerification; 28 29 import java.util.Random; 30 import java.util.concurrent.TimeUnit; 31 32 /** 33 * Set of tests that verifies proper interaction of the sensors in the platform. 34 * 35 * To execute these test cases, the following command can be used: 36 * $ adb shell am instrument -e class android.hardware.cts.SensorIntegrationTests \ 37 * -w android.hardware.cts/android.test.InstrumentationCtsTestRunner 38 */ 39 public class SensorIntegrationTests extends SensorTestCase { 40 private static final String TAG = "SensorIntegrationTests"; 41 42 /** 43 * This test focuses in the interaction of continuous and batching clients for the same Sensor 44 * under test. The verification ensures that sensor clients can interact with the System and 45 * not affect other clients in the way. 46 * 47 * The test verifies for each client that the a set of sampled data arrives in order. However 48 * each client in the test has different set of parameters that represent different types of 49 * clients in the real world. 50 * 51 * A test failure might indicate that the HAL implementation does not respect the assumption 52 * that the sensors must be independent. Activating one sensor should not cause another sensor 53 * to deactivate or to change behavior. 54 * It is however, acceptable that when a client is activated at a higher sampling rate, it would 55 * cause other clients to receive data at a faster sampling rate. A client causing other clients 56 * to receive data at a lower sampling rate is, however, not acceptable. 57 * 58 * The assertion associated with the test failure provides: 59 * - the thread id on which the failure occurred 60 * - the sensor type and sensor handle that caused the failure 61 * - the event that caused the issue 62 * It is important to look at the internals of the Sensor HAL to identify how the interaction 63 * of several clients can lead to the failing state. 64 */ testSensorsWithSeveralClients()65 public void testSensorsWithSeveralClients() throws Throwable { 66 SensorCtsHelper.sleep(3, TimeUnit.SECONDS); 67 final int ITERATIONS = 50; 68 final int MAX_REPORTING_LATENCY_US = (int) TimeUnit.SECONDS.toMicros(5); 69 final Context context = getContext(); 70 71 int sensorTypes[] = { 72 Sensor.TYPE_ACCELEROMETER, 73 Sensor.TYPE_MAGNETIC_FIELD, 74 Sensor.TYPE_GYROSCOPE }; 75 76 ParallelSensorOperation operation = new ParallelSensorOperation(); 77 for(int sensorType : sensorTypes) { 78 TestSensorEnvironment environment = new TestSensorEnvironment( 79 context, 80 sensorType, 81 shouldEmulateSensorUnderLoad(), 82 SensorManager.SENSOR_DELAY_FASTEST); 83 TestSensorOperation continuousOperation = 84 TestSensorOperation.createOperation(environment, 100 /* eventCount */); 85 continuousOperation.addVerification(new EventOrderingVerification()); 86 operation.add(new RepeatingSensorOperation(continuousOperation, ITERATIONS)); 87 88 Sensor sensor = TestSensorEnvironment.getSensor(context, sensorType); 89 TestSensorEnvironment batchingEnvironment = new TestSensorEnvironment( 90 context, 91 sensorType, 92 shouldEmulateSensorUnderLoad(), 93 true, /* isIntegrationTest */ 94 sensor.getMinDelay(), 95 MAX_REPORTING_LATENCY_US); 96 TestSensorOperation batchingOperation = 97 TestSensorOperation.createOperation(batchingEnvironment, 100 /* eventCount */); 98 batchingOperation.addVerification(new EventOrderingVerification()); 99 operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS)); 100 } 101 operation.execute(getCurrentTestNode()); 102 operation.getStats().log(TAG); 103 } 104 105 /** 106 * This test focuses in the interaction of several sensor Clients. The test characterizes by 107 * using clients for different Sensors under Test that vary the sampling rates and report 108 * latencies for the requests. 109 * The verification ensures that the sensor clients can vary the parameters of their requests 110 * without affecting other clients. 111 * 112 * The test verifies for each client that a set of sampled data arrives in order. However each 113 * client in the test has different set of parameters that represent different types of clients 114 * in the real world. 115 * 116 * The test can be susceptible to issues when several clients interacting with the system 117 * actually affect the operation of other clients. 118 * 119 * The assertion associated with the test failure provides: 120 * - the thread id on which the failure occurred 121 * - the sensor type and sensor handle that caused the failure 122 * - the event that caused the issue 123 * It is important to look at the internals of the Sensor HAL to identify how the interaction 124 * of several clients can lead to the failing state. 125 */ testSensorsMovingRates()126 public void testSensorsMovingRates() throws Throwable { 127 SensorCtsHelper.sleep(3, TimeUnit.SECONDS); 128 // use at least two instances to ensure more than one client of any given sensor is in play 129 final int INSTANCES_TO_USE = 5; 130 final int ITERATIONS_TO_EXECUTE = 100; 131 132 ParallelSensorOperation operation = new ParallelSensorOperation(); 133 int sensorTypes[] = { 134 Sensor.TYPE_ACCELEROMETER, 135 Sensor.TYPE_MAGNETIC_FIELD, 136 Sensor.TYPE_GYROSCOPE }; 137 138 Context context = getContext(); 139 for(int sensorType : sensorTypes) { 140 for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) { 141 SequentialSensorOperation sequentialOperation = new SequentialSensorOperation(); 142 for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) { 143 TestSensorEnvironment environment = new TestSensorEnvironment( 144 context, 145 sensorType, 146 shouldEmulateSensorUnderLoad(), 147 true, /* isIntegrationTest */ 148 generateSamplingRateInUs(sensorType), 149 generateReportLatencyInUs()); 150 TestSensorOperation sensorOperation = 151 TestSensorOperation.createOperation(environment, 100 /* eventCount */); 152 sensorOperation.addVerification(new EventOrderingVerification()); 153 sequentialOperation.add(sensorOperation); 154 } 155 operation.add(sequentialOperation); 156 } 157 } 158 159 operation.execute(getCurrentTestNode()); 160 operation.getStats().log(TAG); 161 } 162 163 /** 164 * Regress: 165 * - b/10641388 166 */ 167 testAccelerometerAccelerometerStopping()168 public void testAccelerometerAccelerometerStopping() throws Throwable { 169 verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER); 170 } 171 testAccelerometerGyroscopeStopping()172 public void testAccelerometerGyroscopeStopping() throws Throwable { 173 verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE); 174 } 175 testAccelerometerMagneticFieldStopping()176 public void testAccelerometerMagneticFieldStopping() throws Throwable { 177 verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD); 178 } 179 testGyroscopeAccelerometerStopping()180 public void testGyroscopeAccelerometerStopping() throws Throwable { 181 verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER); 182 } 183 testGyroscopeGyroscopeStopping()184 public void testGyroscopeGyroscopeStopping() throws Throwable { 185 verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_GYROSCOPE); 186 } 187 testGyroscopeMagneticFieldStopping()188 public void testGyroscopeMagneticFieldStopping() throws Throwable { 189 verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD); 190 } 191 testMagneticFieldAccelerometerStopping()192 public void testMagneticFieldAccelerometerStopping() throws Throwable { 193 verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_ACCELEROMETER); 194 } 195 testMagneticFieldGyroscopeStopping()196 public void testMagneticFieldGyroscopeStopping() throws Throwable { 197 verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE); 198 } 199 testMagneticFieldMagneticFieldStopping()200 public void testMagneticFieldMagneticFieldStopping() throws Throwable { 201 verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD); 202 } 203 204 /** 205 * This test verifies that starting/stopping a particular Sensor client in the System does not 206 * affect other sensor clients. 207 * the test is used to validate that starting/stopping operations are independent on several 208 * sensor clients. 209 * 210 * The test verifies for each client that the a set of sampled data arrives in order. However 211 * each client in the test has different set of parameters that represent different types of 212 * clients in the real world. 213 * 214 * The test can be susceptible to issues when several clients interacting with the system 215 * actually affect the operation of other clients. 216 * 217 * The assertion associated with the test failure provides: 218 * - the thread id on which the failure occurred 219 * - the sensor type and sensor handle that caused the failure 220 * - the event that caused the issue 221 * It is important to look at the internals of the Sensor HAL to identify how the interaction 222 * of several clients can lead to the failing state. 223 */ verifySensorStoppingInteraction( int sensorTypeTestee, int sensorTypeTester)224 public void verifySensorStoppingInteraction( 225 int sensorTypeTestee, 226 int sensorTypeTester) throws Throwable { 227 SensorCtsHelper.sleep(3, TimeUnit.SECONDS); 228 Context context = getContext(); 229 230 TestSensorEnvironment testerEnvironment = new TestSensorEnvironment( 231 context, 232 sensorTypeTester, 233 shouldEmulateSensorUnderLoad(), 234 SensorManager.SENSOR_DELAY_FASTEST); 235 TestSensorOperation tester = 236 TestSensorOperation.createOperation(testerEnvironment, 100 /* event count */); 237 tester.addVerification(new EventOrderingVerification()); 238 239 TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment( 240 context, 241 sensorTypeTestee, 242 shouldEmulateSensorUnderLoad(), 243 SensorManager.SENSOR_DELAY_FASTEST); 244 TestSensorOperation testee = 245 TestSensorOperation.createOperation(testeeEnvironment, 100 /* event count */); 246 testee.addVerification(new EventOrderingVerification()); 247 248 ParallelSensorOperation operation = new ParallelSensorOperation(); 249 operation.add(tester, testee); 250 operation.execute(getCurrentTestNode()); 251 operation.getStats().log(TAG); 252 253 testee = testee.clone(); 254 testee.execute(getCurrentTestNode()); 255 testee.getStats().log(TAG); 256 } 257 258 /** 259 * Private helpers. 260 */ 261 private final Random mGenerator = new Random(); 262 generateSamplingRateInUs(int sensorType)263 private int generateSamplingRateInUs(int sensorType) { 264 int rate; 265 switch(mGenerator.nextInt(5)) { 266 case 0: 267 rate = SensorManager.SENSOR_DELAY_FASTEST; 268 break; 269 default: 270 Sensor sensor = TestSensorEnvironment.getSensor(getContext(), sensorType); 271 int maxSamplingRate = sensor.getMinDelay(); 272 rate = maxSamplingRate * mGenerator.nextInt(10); 273 } 274 return rate; 275 } 276 generateReportLatencyInUs()277 private int generateReportLatencyInUs() { 278 long reportLatencyUs = TimeUnit.SECONDS.toMicros(mGenerator.nextInt(5) + 1); 279 return (int) reportLatencyUs; 280 } 281 } 282