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