1 /*
2  * Copyright (C) 2014 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 
17 package android.hardware.cts.helpers;
18 
19 import android.content.Context;
20 import android.hardware.Sensor;
21 import android.hardware.SensorManager;
22 import android.hardware.cts.helpers.sensoroperations.SensorOperation;
23 
24 import java.util.concurrent.TimeUnit;
25 
26 /* TODO: Refactor constructors into a builder */
27 
28 /**
29  * A class that encapsulates base environment information for the {@link SensorOperation}.
30  * The environment is self contained and carries its state around all the sensor test framework.
31  */
32 public class TestSensorEnvironment {
33 
34     /**
35      * It represents the fraction of the expected sampling frequency, at which the sensor can
36      * actually produce events.
37      */
38     private static final float MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER = 0.9f;
39 
40     private final Context mContext;
41     private final Sensor mSensor;
42     private final boolean mSensorMightHaveMoreListeners;
43     private final int mSamplingPeriodUs;
44     private final int mMaxReportLatencyUs;
45     private final boolean mIsDeviceSuspendTest;
46     private final boolean mIsIntegrationTest;
47     private final boolean mIsAutomotiveSpecificTest;
48 
49     /**
50      * Constructs an environment for sensor testing.
51      *
52      * @param context The context for the test
53      * @param sensorType The type of the sensor under test
54      * @param samplingPeriodUs The requested collection period for the sensor under test
55      *
56      * @deprecated Use variants with {@link Sensor} objects.
57      */
58     @Deprecated
TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs)59     public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) {
60         this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs);
61     }
62 
63     /**
64      * Constructs an environment for sensor testing.
65      *
66      * @param context The context for the test
67      * @param sensorType The type of the sensor under test
68      * @param samplingPeriodUs The requested collection period for the sensor under test
69      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
70      *
71      * @deprecated Use variants with {@link Sensor} objects.
72      */
73     @Deprecated
TestSensorEnvironment( Context context, int sensorType, int samplingPeriodUs, int maxReportLatencyUs)74     public TestSensorEnvironment(
75             Context context,
76             int sensorType,
77             int samplingPeriodUs,
78             int maxReportLatencyUs) {
79         this(context,
80                 sensorType,
81                 false /* sensorMightHaveMoreListeners */,
82                 samplingPeriodUs,
83                 maxReportLatencyUs);
84     }
85 
86     /**
87      * Constructs an environment for sensor testing.
88      *
89      * @param context The context for the test
90      * @param sensorType The type of the sensor under test
91      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
92      * @param samplingPeriodUs The requested collection period for the sensor under test
93      *
94      * @deprecated Use variants with {@link Sensor} objects.
95      */
96     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs)97     public TestSensorEnvironment(
98             Context context,
99             int sensorType,
100             boolean sensorMightHaveMoreListeners,
101             int samplingPeriodUs) {
102         this(context,
103                 sensorType,
104                 sensorMightHaveMoreListeners,
105                 samplingPeriodUs,
106                 0 /* maxReportLatencyUs */);
107     }
108 
109     /**
110      * Constructs an environment for sensor testing.
111      *
112      * @param context The context for the test
113      * @param sensorType The type of the sensor under test
114      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
115      * @param samplingPeriodUs The requested collection period for the sensor under test
116      * @param isAutomotiveSpecificTest Whether this is an automotive specific test
117      *
118      * @deprecated Use variants with {@link Sensor} objects.
119      */
120     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, boolean isAutomotiveSpecificTest)121     public TestSensorEnvironment(
122             Context context,
123             int sensorType,
124             boolean sensorMightHaveMoreListeners,
125             int samplingPeriodUs,
126             boolean isAutomotiveSpecificTest) {
127         this(context,
128                 getSensor(context, sensorType),
129                 sensorMightHaveMoreListeners,
130                 samplingPeriodUs,
131                 0 /* maxReportLatencyUs */,
132                 false,
133                 false,
134                 isAutomotiveSpecificTest);
135     }
136 
137     /**
138      * Constructs an environment for sensor testing.
139      *
140      * @param context The context for the test
141      * @param sensorType The type of the sensor under test
142      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
143      * @param samplingPeriodUs The requested collection period for the sensor under test
144      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
145      *
146      * @deprecated Use variants with {@link Sensor} objects.
147      */
148     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs)149     public TestSensorEnvironment(
150             Context context,
151             int sensorType,
152             boolean sensorMightHaveMoreListeners,
153             int samplingPeriodUs,
154             int maxReportLatencyUs) {
155         this(context,
156                 getSensor(context, sensorType),
157                 sensorMightHaveMoreListeners,
158                 samplingPeriodUs,
159                 maxReportLatencyUs);
160     }
161 
162     /**
163      * Constructs an environment for sensor testing.
164      *
165      * @param context The context for the test
166      * @param sensorType The type of the sensor under test
167      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
168      * @param isIntegrationTest Whether this is an integration test (more than one sensor actived)
169      * @param samplingPeriodUs The requested collection period for the sensor under test
170      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
171      *
172      * @deprecated Use variants with {@link Sensor} objects.
173      */
174     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, boolean isIntegrationTest, int samplingPeriodUs, int maxReportLatencyUs)175     public TestSensorEnvironment(
176             Context context,
177             int sensorType,
178             boolean sensorMightHaveMoreListeners,
179             boolean isIntegrationTest,
180             int samplingPeriodUs,
181             int maxReportLatencyUs) {
182         this(context,
183                 getSensor(context, sensorType),
184                 sensorMightHaveMoreListeners,
185                 isIntegrationTest,
186                 samplingPeriodUs,
187                 maxReportLatencyUs);
188     }
189 
190     /**
191      * Constructs an environment for sensor testing.
192      *
193      * @param context The context for the test
194      * @param sensor The sensor under test
195      * @param samplingPeriodUs The requested collection period for the sensor under test
196      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
197      */
TestSensorEnvironment( Context context, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)198     public TestSensorEnvironment(
199             Context context,
200             Sensor sensor,
201             int samplingPeriodUs,
202             int maxReportLatencyUs) {
203         this(context,
204                 sensor,
205                 false /* sensorMightHaveMoreListeners */,
206                 samplingPeriodUs,
207                 maxReportLatencyUs);
208     }
209 
210     /**
211      * Constructs an environment for sensor testing.
212      *
213      * @param context The context for the test
214      * @param sensor The sensor under test
215      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this
216      *                                     usually implies that there are several listeners
217      *                                     requesting different sampling periods)
218      * @param samplingPeriodUs The requested collection period for the sensor under test
219      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
220      */
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs)221     public TestSensorEnvironment(
222             Context context,
223             Sensor sensor,
224             boolean sensorMightHaveMoreListeners,
225             int samplingPeriodUs,
226             int maxReportLatencyUs) {
227         this(context,
228                 sensor,
229                 sensorMightHaveMoreListeners,
230                 samplingPeriodUs,
231                 maxReportLatencyUs,
232                 false /* isDeviceSuspendTest */);
233     }
234 
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, boolean isIntegrationTest, int samplingPeriodUs, int maxReportLatencyUs)235     public TestSensorEnvironment(
236             Context context,
237             Sensor sensor,
238             boolean sensorMightHaveMoreListeners,
239             boolean isIntegrationTest,
240             int samplingPeriodUs,
241             int maxReportLatencyUs) {
242         this(context,
243                 sensor,
244                 sensorMightHaveMoreListeners,
245                 samplingPeriodUs,
246                 maxReportLatencyUs,
247                 false /* isDeviceSuspendTest */,
248                 isIntegrationTest,
249                 false /* isAutomotiveSpecificTest */);
250     }
251 
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs, boolean isDeviceSuspendTest)252     public TestSensorEnvironment(
253             Context context,
254             Sensor sensor,
255             boolean sensorMightHaveMoreListeners,
256             int samplingPeriodUs,
257             int maxReportLatencyUs,
258             boolean isDeviceSuspendTest) {
259         this(context, sensor, sensorMightHaveMoreListeners,
260                 samplingPeriodUs, maxReportLatencyUs,
261                 isDeviceSuspendTest,
262                 false /* isIntegrationTest */,
263                 false /* isAutomotiveSpecificTest */);
264     }
265 
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs, boolean isDeviceSuspendTest, boolean isIntegrationTest, boolean isAutomotiveSpecificTest)266     public TestSensorEnvironment(
267             Context context,
268             Sensor sensor,
269             boolean sensorMightHaveMoreListeners,
270             int samplingPeriodUs,
271             int maxReportLatencyUs,
272             boolean isDeviceSuspendTest,
273             boolean isIntegrationTest,
274             boolean isAutomotiveSpecificTest) {
275         mContext = context;
276         mSensor = sensor;
277         mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners;
278         mSamplingPeriodUs = samplingPeriodUs;
279         mMaxReportLatencyUs = maxReportLatencyUs;
280         mIsDeviceSuspendTest = isDeviceSuspendTest;
281         mIsIntegrationTest = isIntegrationTest;
282         mIsAutomotiveSpecificTest = isAutomotiveSpecificTest;
283     }
284 
285     /**
286      * @return The context instance associated with the test.
287      */
getContext()288     public Context getContext() {
289         return mContext;
290     }
291 
292     /**
293      * @return The sensor under test.
294      */
getSensor()295     public Sensor getSensor() {
296         return mSensor;
297     }
298 
299     /**
300      * @return The requested collection rate in microseconds.
301      */
getRequestedSamplingPeriodUs()302     public int getRequestedSamplingPeriodUs() {
303         return mSamplingPeriodUs;
304     }
305 
306     /**
307      * @return The frequency equivalent to {@link #getRequestedSamplingPeriodUs()}.
308      */
getFrequencyHz()309     public double getFrequencyHz() {
310         return SensorCtsHelper.getFrequency(mSamplingPeriodUs, TimeUnit.MICROSECONDS);
311     }
312 
313     /**
314      * @return A string representing the frequency equivalent to
315      * {@link #getRequestedSamplingPeriodUs()}.
316      */
getFrequencyString()317     public String getFrequencyString() {
318         if (mSamplingPeriodUs == SensorManager.SENSOR_DELAY_FASTEST) {
319             return "fastest";
320         }
321         return String.format("%.2fhz", getFrequencyHz());
322     }
323 
324     /**
325      * @return The requested collection max batch report latency in microseconds.
326      */
getMaxReportLatencyUs()327     public int getMaxReportLatencyUs() {
328         return mMaxReportLatencyUs;
329     }
330 
331     /**
332      * Returns {@code true} if there might be other listeners of {@link #getSensor()} requesting
333      * data at different sampling rates (the rates are unknown); false otherwise.
334      */
isSensorSamplingRateOverloaded()335     public boolean isSensorSamplingRateOverloaded() {
336         return mSensorMightHaveMoreListeners
337                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
338     }
339 
340     /**
341      * Convert the {@link #getRequestedSamplingPeriodUs()} into delay in microseconds.
342      * <p>
343      * The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does
344      * not specify values for these flags. The rate is set to the max of
345      * {@link Sensor#getMinDelay()} and the rate given.
346      * </p>
347      */
getExpectedSamplingPeriodUs()348     public int getExpectedSamplingPeriodUs() {
349         if (!isDelayRateTestable()) {
350             throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]");
351         }
352 
353         int expectedSamplingPeriodUs = mSamplingPeriodUs;
354         int sensorMaxDelay = mSensor.getMaxDelay();
355         if (sensorMaxDelay > 0) {
356             expectedSamplingPeriodUs = Math.min(expectedSamplingPeriodUs, sensorMaxDelay);
357         }
358 
359         return Math.max(expectedSamplingPeriodUs, mSensor.getMinDelay());
360     }
361 
362     /**
363      * Calculate the maximum expected sampling period in us.
364      * @return The maximum acceptable actual sampling period of this sensor.
365      *         For continuous sensors, this is higher than {@link #getExpectedSamplingPeriodUs()}
366      *         because sensors are allowed to run up to 10% slower than requested.
367      *         For sensors with other reporting modes, this is the maximum integer
368      *         {@link Integer#MAX_VALUE} as they can report no events for long
369      *         periods of time.
370      */
getMaximumExpectedSamplingPeriodUs()371     public int getMaximumExpectedSamplingPeriodUs() {
372         int sensorReportingMode = mSensor.getReportingMode();
373         if (sensorReportingMode != Sensor.REPORTING_MODE_CONTINUOUS) {
374             return Integer.MAX_VALUE;
375         }
376 
377         int expectedSamplingPeriodUs = getExpectedSamplingPeriodUs();
378         return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER);
379     }
380 
381 
382     /**
383      * Calculate the allowed sensor start delay.
384      *
385      * CDD Section 7.3:
386      * MUST report the first sensor sample within 400 milliseconds + 2 * sample_time of the
387      * sensor being activated. It is acceptable for this sample to have an accuracy of 0.
388      *
389      * [CDD] Keep this updated with CDD.
390      */
getAllowedSensorStartDelay()391     public long getAllowedSensorStartDelay() {
392         return TimeUnit.MILLISECONDS.toMicros(400) + 2 * getMaximumExpectedSamplingPeriodUs();
393     }
394 
395     /**
396      * @return The number of axes in the coordinate system of the sensor under test.
397      */
getSensorAxesCount()398     public int getSensorAxesCount() {
399         switch (mSensor.getType()) {
400             case Sensor.TYPE_GYROSCOPE:
401                 return 3;
402             default:
403                 throw new IllegalStateException("Axes count needs to be defined for sensor type: "
404                         + mSensor.getStringType());
405         }
406     }
407 
408     /**
409      * Get the default sensor for a given type.
410      *
411      * @deprecated Used for historical reasons, sensor tests must be written around Sensor objects,
412      * so all sensors of a given type are exercised.
413      */
414     @Deprecated
getSensor(Context context, int sensorType)415     public static Sensor getSensor(Context context, int sensorType) {
416         SensorManager sensorManager =
417                 (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
418         if (sensorManager == null) {
419             throw new IllegalStateException("SensorService is not present in the system.");
420         }
421 
422         Sensor sensor = sensorManager.getDefaultSensor(sensorType);
423         if(sensor == null) {
424             throw new SensorNotSupportedException(sensorType);
425         }
426         return sensor;
427     }
428 
429     /**
430      * @return The maximum latency of a given sensor, on top of {@link #getMaxReportLatencyUs()}.
431      *
432      * NOTE: The latency is defined as the time between the event happens and the time the event is
433      * generated.
434      *
435      * - At time event_time (reported in the sensor event), the physical event happens
436      * - At time event_time + detection_latency, the physical event is detected and the event is
437      *   saved in the hardware fifo
438      * - At time event_time + detection_latency + report_latency, the event is reported through the
439      *   HAL
440      *
441      * Soon after that, the event is piped through the framework to the application. This time may
442      * vary depending on the CPU load. The time 'detection_latency' must be less than
443      * {@link #getSensorMaxDetectionLatencyNs(Sensor)}, and 'report_latency' must be less than
444      * {@link #getMaxReportLatencyUs()} passed through batch() at the HAL level.
445      */
446     // TODO: when all tests are moved to use the Sensor test framework, make this method non-static
getSensorMaxDetectionLatencyNs(Sensor sensor)447     public static long getSensorMaxDetectionLatencyNs(Sensor sensor) {
448         int reportLatencySec;
449         switch (sensor.getType()) {
450             case Sensor.TYPE_STEP_DETECTOR:
451                 reportLatencySec = 2;
452                 break;
453             case Sensor.TYPE_STEP_COUNTER:
454                 reportLatencySec = 10;
455                 break;
456             case Sensor.TYPE_SIGNIFICANT_MOTION:
457                 reportLatencySec = 10;
458                 break;
459             default:
460                 reportLatencySec = 0;
461         }
462         return TimeUnit.SECONDS.toNanos(reportLatencySec);
463     }
464 
465     @Override
toString()466     public String toString() {
467         return String.format(
468                 "Sensor='%s', SamplingRateOverloaded=%s, SamplingPeriod=%sus, "
469                         + "MaxReportLatency=%sus",
470                 mSensor,
471                 isSensorSamplingRateOverloaded(),
472                 mSamplingPeriodUs,
473                 mMaxReportLatencyUs);
474     }
475 
476     /**
477      * Return true if {@link #getRequestedSamplingPeriodUs()} is not one of
478      * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or
479      * {@link SensorManager#SENSOR_DELAY_NORMAL}.
480      */
isDelayRateTestable()481     private boolean isDelayRateTestable() {
482         return (mSamplingPeriodUs >= 0
483                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_GAME
484                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_UI
485                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_NORMAL);
486     }
487 
isDeviceSuspendTest()488     public boolean isDeviceSuspendTest() {
489         return mIsDeviceSuspendTest;
490     }
491 
isIntegrationTest()492     public boolean isIntegrationTest() {
493         return mIsIntegrationTest;
494     }
495 
isAutomotiveSpecificTest()496     public boolean isAutomotiveSpecificTest() {
497         return mIsAutomotiveSpecificTest;
498     }
499 }
500 
501