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 com.android.cts.hardware/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                     sensor.getMinDelay(),
94                     MAX_REPORTING_LATENCY_US);
95             TestSensorOperation batchingOperation =
96                     TestSensorOperation.createOperation(batchingEnvironment, 100 /* eventCount */);
97             batchingOperation.addVerification(new EventOrderingVerification());
98             operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS));
99         }
100         operation.execute(getCurrentTestNode());
101         operation.getStats().log(TAG);
102     }
103 
104     /**
105      * This test focuses in the interaction of several sensor Clients. The test characterizes by
106      * using clients for different Sensors under Test that vary the sampling rates and report
107      * latencies for the requests.
108      * The verification ensures that the sensor clients can vary the parameters of their requests
109      * without affecting other clients.
110      *
111      * The test verifies for each client that a set of sampled data arrives in order. However each
112      * client in the test has different set of parameters that represent different types of clients
113      * in the real world.
114      *
115      * The test can be susceptible to issues when several clients interacting with the system
116      * actually affect the operation of other clients.
117      *
118      * The assertion associated with the test failure provides:
119      * - the thread id on which the failure occurred
120      * - the sensor type and sensor handle that caused the failure
121      * - the event that caused the issue
122      * It is important to look at the internals of the Sensor HAL to identify how the interaction
123      * of several clients can lead to the failing state.
124      */
testSensorsMovingRates()125     public void testSensorsMovingRates() throws Throwable {
126         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
127         // use at least two instances to ensure more than one client of any given sensor is in play
128         final int INSTANCES_TO_USE = 5;
129         final int ITERATIONS_TO_EXECUTE = 100;
130 
131         ParallelSensorOperation operation = new ParallelSensorOperation();
132         int sensorTypes[] = {
133                 Sensor.TYPE_ACCELEROMETER,
134                 Sensor.TYPE_MAGNETIC_FIELD,
135                 Sensor.TYPE_GYROSCOPE };
136 
137         Context context = getContext();
138         for(int sensorType : sensorTypes) {
139             for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) {
140                 SequentialSensorOperation sequentialOperation = new SequentialSensorOperation();
141                 for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) {
142                     TestSensorEnvironment environment = new TestSensorEnvironment(
143                             context,
144                             sensorType,
145                             shouldEmulateSensorUnderLoad(),
146                             generateSamplingRateInUs(sensorType),
147                             generateReportLatencyInUs());
148                     TestSensorOperation sensorOperation =
149                             TestSensorOperation.createOperation(environment, 100 /* eventCount */);
150                     sensorOperation.addVerification(new EventOrderingVerification());
151                     sequentialOperation.add(sensorOperation);
152                 }
153                 operation.add(sequentialOperation);
154             }
155         }
156 
157         operation.execute(getCurrentTestNode());
158         operation.getStats().log(TAG);
159     }
160 
161     /**
162      * Regress:
163      * - b/10641388
164      */
165 
testAccelerometerAccelerometerStopping()166     public void testAccelerometerAccelerometerStopping()  throws Throwable {
167         verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER);
168     }
169 
testAccelerometerGyroscopeStopping()170     public void testAccelerometerGyroscopeStopping()  throws Throwable {
171         verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE);
172     }
173 
testAccelerometerMagneticFieldStopping()174     public void testAccelerometerMagneticFieldStopping()  throws Throwable {
175         verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD);
176     }
177 
testGyroscopeAccelerometerStopping()178     public void testGyroscopeAccelerometerStopping()  throws Throwable {
179         verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER);
180     }
181 
testGyroscopeGyroscopeStopping()182     public void testGyroscopeGyroscopeStopping()  throws Throwable {
183         verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_GYROSCOPE);
184     }
185 
testGyroscopeMagneticFieldStopping()186     public void testGyroscopeMagneticFieldStopping()  throws Throwable {
187         verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD);
188     }
189 
testMagneticFieldAccelerometerStopping()190     public void testMagneticFieldAccelerometerStopping()  throws Throwable {
191         verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_ACCELEROMETER);
192     }
193 
testMagneticFieldGyroscopeStopping()194     public void testMagneticFieldGyroscopeStopping()  throws Throwable {
195         verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE);
196     }
197 
testMagneticFieldMagneticFieldStopping()198     public void testMagneticFieldMagneticFieldStopping()  throws Throwable {
199         verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD);
200     }
201 
202     /**
203      * This test verifies that starting/stopping a particular Sensor client in the System does not
204      * affect other sensor clients.
205      * the test is used to validate that starting/stopping operations are independent on several
206      * sensor clients.
207      *
208      * The test verifies for each client that the a set of sampled data arrives in order. However
209      * each client in the test has different set of parameters that represent different types of
210      * clients in the real world.
211      *
212      * The test can be susceptible to issues when several clients interacting with the system
213      * actually affect the operation of other clients.
214      *
215      * The assertion associated with the test failure provides:
216      * - the thread id on which the failure occurred
217      * - the sensor type and sensor handle that caused the failure
218      * - the event that caused the issue
219      * It is important to look at the internals of the Sensor HAL to identify how the interaction
220      * of several clients can lead to the failing state.
221      */
verifySensorStoppingInteraction( int sensorTypeTestee, int sensorTypeTester)222     public void verifySensorStoppingInteraction(
223             int sensorTypeTestee,
224             int sensorTypeTester) throws Throwable {
225         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
226         Context context = getContext();
227 
228         TestSensorEnvironment testerEnvironment = new TestSensorEnvironment(
229                 context,
230                 sensorTypeTester,
231                 shouldEmulateSensorUnderLoad(),
232                 SensorManager.SENSOR_DELAY_FASTEST);
233         TestSensorOperation tester =
234                 TestSensorOperation.createOperation(testerEnvironment, 100 /* event count */);
235         tester.addVerification(new EventOrderingVerification());
236 
237         TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment(
238                 context,
239                 sensorTypeTestee,
240                 shouldEmulateSensorUnderLoad(),
241                 SensorManager.SENSOR_DELAY_FASTEST);
242         TestSensorOperation testee =
243                 TestSensorOperation.createOperation(testeeEnvironment, 100 /* event count */);
244         testee.addVerification(new EventOrderingVerification());
245 
246         ParallelSensorOperation operation = new ParallelSensorOperation();
247         operation.add(tester, testee);
248         operation.execute(getCurrentTestNode());
249         operation.getStats().log(TAG);
250 
251         testee = testee.clone();
252         testee.execute(getCurrentTestNode());
253         testee.getStats().log(TAG);
254     }
255 
256     /**
257      * Private helpers.
258      */
259     private final Random mGenerator = new Random();
260 
generateSamplingRateInUs(int sensorType)261     private int generateSamplingRateInUs(int sensorType) {
262         int rate;
263         switch(mGenerator.nextInt(5)) {
264             case 0:
265                 rate = SensorManager.SENSOR_DELAY_FASTEST;
266                 break;
267             default:
268                 Sensor sensor = TestSensorEnvironment.getSensor(getContext(), sensorType);
269                 int maxSamplingRate = sensor.getMinDelay();
270                 rate = maxSamplingRate * mGenerator.nextInt(10);
271         }
272         return rate;
273     }
274 
generateReportLatencyInUs()275     private int generateReportLatencyInUs() {
276         long reportLatencyUs = TimeUnit.SECONDS.toMicros(mGenerator.nextInt(5) + 1);
277         return (int) reportLatencyUs;
278     }
279 }
280