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