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 /**
27  * A class that encapsulates base environment information for the {@link SensorOperation}.
28  * The environment is self contained and carries its state around all the sensor test framework.
29  */
30 public class TestSensorEnvironment {
31 
32     /**
33      * It represents the fraction of the expected sampling frequency, at which the sensor can
34      * actually produce events.
35      */
36     private static final float MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER = 0.9f;
37 
38     private final Context mContext;
39     private final Sensor mSensor;
40     private final boolean mSensorMightHaveMoreListeners;
41     private final int mSamplingPeriodUs;
42     private final int mMaxReportLatencyUs;
43     private final boolean mIsDeviceSuspendTest;
44 
45     /**
46      * Constructs an environment for sensor testing.
47      *
48      * @param context The context for the test
49      * @param sensorType The type of the sensor under test
50      * @param samplingPeriodUs The requested collection period for the sensor under test
51      *
52      * @deprecated Use variants with {@link Sensor} objects.
53      */
54     @Deprecated
TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs)55     public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) {
56         this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs);
57     }
58 
59     /**
60      * Constructs an environment for sensor testing.
61      *
62      * @param context The context for the test
63      * @param sensorType The type of the sensor under test
64      * @param samplingPeriodUs The requested collection period for the sensor under test
65      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
66      *
67      * @deprecated Use variants with {@link Sensor} objects.
68      */
69     @Deprecated
TestSensorEnvironment( Context context, int sensorType, int samplingPeriodUs, int maxReportLatencyUs)70     public TestSensorEnvironment(
71             Context context,
72             int sensorType,
73             int samplingPeriodUs,
74             int maxReportLatencyUs) {
75         this(context,
76                 sensorType,
77                 false /* sensorMightHaveMoreListeners */,
78                 samplingPeriodUs,
79                 maxReportLatencyUs);
80     }
81 
82     /**
83      * Constructs an environment for sensor testing.
84      *
85      * @param context The context for the test
86      * @param sensorType The type of the sensor under test
87      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
88      * @param samplingPeriodUs The requested collection period for the sensor under test
89      *
90      * @deprecated Use variants with {@link Sensor} objects.
91      */
92     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs)93     public TestSensorEnvironment(
94             Context context,
95             int sensorType,
96             boolean sensorMightHaveMoreListeners,
97             int samplingPeriodUs) {
98         this(context,
99                 sensorType,
100                 sensorMightHaveMoreListeners,
101                 samplingPeriodUs,
102                 0 /* maxReportLatencyUs */);
103     }
104 
105     /**
106      * Constructs an environment for sensor testing.
107      *
108      * @param context The context for the test
109      * @param sensorType The type of the sensor under test
110      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
111      * @param samplingPeriodUs The requested collection period for the sensor under test
112      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
113      *
114      * @deprecated Use variants with {@link Sensor} objects.
115      */
116     @Deprecated
TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs)117     public TestSensorEnvironment(
118             Context context,
119             int sensorType,
120             boolean sensorMightHaveMoreListeners,
121             int samplingPeriodUs,
122             int maxReportLatencyUs) {
123         this(context,
124                 getSensor(context, sensorType),
125                 sensorMightHaveMoreListeners,
126                 samplingPeriodUs,
127                 maxReportLatencyUs);
128     }
129 
130     /**
131      * Constructs an environment for sensor testing.
132      *
133      * @param context The context for the test
134      * @param sensor The sensor under test
135      * @param samplingPeriodUs The requested collection period for the sensor under test
136      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
137      */
TestSensorEnvironment( Context context, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs)138     public TestSensorEnvironment(
139             Context context,
140             Sensor sensor,
141             int samplingPeriodUs,
142             int maxReportLatencyUs) {
143         this(context,
144                 sensor,
145                 false /* sensorMightHaveMoreListeners */,
146                 samplingPeriodUs,
147                 maxReportLatencyUs);
148     }
149 
150     /**
151      * Constructs an environment for sensor testing.
152      *
153      * @param context The context for the test
154      * @param sensor The sensor under test
155      * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this
156      *                                     usually implies that there are several listeners
157      *                                     requesting different sampling periods)
158      * @param samplingPeriodUs The requested collection period for the sensor under test
159      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
160      */
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs)161     public TestSensorEnvironment(
162             Context context,
163             Sensor sensor,
164             boolean sensorMightHaveMoreListeners,
165             int samplingPeriodUs,
166             int maxReportLatencyUs) {
167         this(context,
168                 sensor,
169                 sensorMightHaveMoreListeners,
170                 samplingPeriodUs,
171                 maxReportLatencyUs,
172                 false /* isDeviceSuspendTest */);
173     }
174 
TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs, boolean isDeviceSuspendTest)175     public TestSensorEnvironment(
176             Context context,
177             Sensor sensor,
178             boolean sensorMightHaveMoreListeners,
179             int samplingPeriodUs,
180             int maxReportLatencyUs,
181             boolean isDeviceSuspendTest) {
182         mContext = context;
183         mSensor = sensor;
184         mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners;
185         mSamplingPeriodUs = samplingPeriodUs;
186         mMaxReportLatencyUs = maxReportLatencyUs;
187         mIsDeviceSuspendTest = isDeviceSuspendTest;
188     }
189 
190     /**
191      * @return The context instance associated with the test.
192      */
getContext()193     public Context getContext() {
194         return mContext;
195     }
196 
197     /**
198      * @return The sensor under test.
199      */
getSensor()200     public Sensor getSensor() {
201         return mSensor;
202     }
203 
204     /**
205      * @return The requested collection rate in microseconds.
206      */
getRequestedSamplingPeriodUs()207     public int getRequestedSamplingPeriodUs() {
208         return mSamplingPeriodUs;
209     }
210 
211     /**
212      * @return The frequency equivalent to {@link #getRequestedSamplingPeriodUs()}.
213      */
getFrequencyHz()214     public double getFrequencyHz() {
215         return SensorCtsHelper.getFrequency(mSamplingPeriodUs, TimeUnit.MICROSECONDS);
216     }
217 
218     /**
219      * @return A string representing the frequency equivalent to
220      * {@link #getRequestedSamplingPeriodUs()}.
221      */
getFrequencyString()222     public String getFrequencyString() {
223         if (mSamplingPeriodUs == SensorManager.SENSOR_DELAY_FASTEST) {
224             return "fastest";
225         }
226         return String.format("%.2fhz", getFrequencyHz());
227     }
228 
229     /**
230      * @return The requested collection max batch report latency in microseconds.
231      */
getMaxReportLatencyUs()232     public int getMaxReportLatencyUs() {
233         return mMaxReportLatencyUs;
234     }
235 
236     /**
237      * Returns {@code true} if there might be other listeners of {@link #getSensor()} requesting
238      * data at different sampling rates (the rates are unknown); false otherwise.
239      */
isSensorSamplingRateOverloaded()240     public boolean isSensorSamplingRateOverloaded() {
241         return mSensorMightHaveMoreListeners
242                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
243     }
244 
245     /**
246      * Convert the {@link #getRequestedSamplingPeriodUs()} into delay in microseconds.
247      * <p>
248      * The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does
249      * not specify values for these flags. The rate is set to the max of
250      * {@link Sensor#getMinDelay()} and the rate given.
251      * </p>
252      */
getExpectedSamplingPeriodUs()253     public int getExpectedSamplingPeriodUs() {
254         if (!isDelayRateTestable()) {
255             throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]");
256         }
257 
258         int expectedSamplingPeriodUs = mSamplingPeriodUs;
259         int sensorMaxDelay = mSensor.getMaxDelay();
260         if (sensorMaxDelay > 0) {
261             expectedSamplingPeriodUs = Math.min(expectedSamplingPeriodUs, sensorMaxDelay);
262         }
263 
264         return Math.max(expectedSamplingPeriodUs, mSensor.getMinDelay());
265     }
266 
267     /**
268      * @return The maximum acceptable actual sampling period of this sensor.
269      *         For continuous sensors, this is higher than {@link #getExpectedSamplingPeriodUs()}
270      *         because sensors are allowed to run up to 10% slower than requested.
271      *         For sensors with other reporting modes, this is the maximum integer
272      *         {@link Integer#MAX_VALUE} as they can report no events for long
273      *         periods of time.
274      */
getMaximumExpectedSamplingPeriodUs()275     public int getMaximumExpectedSamplingPeriodUs() {
276         int sensorReportingMode = mSensor.getReportingMode();
277         if (sensorReportingMode != Sensor.REPORTING_MODE_CONTINUOUS) {
278             return Integer.MAX_VALUE;
279         }
280 
281         int expectedSamplingPeriodUs = getExpectedSamplingPeriodUs();
282         return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER);
283     }
284 
285     /**
286      * @return The number of axes in the coordinate system of the sensor under test.
287      */
getSensorAxesCount()288     public int getSensorAxesCount() {
289         switch (mSensor.getType()) {
290             case Sensor.TYPE_GYROSCOPE:
291                 return 3;
292             default:
293                 throw new IllegalStateException("Axes count needs to be defined for sensor type: "
294                         + mSensor.getStringType());
295         }
296     }
297 
298     /**
299      * Get the default sensor for a given type.
300      *
301      * @deprecated Used for historical reasons, sensor tests must be written around Sensor objects,
302      * so all sensors of a given type are exercised.
303      */
304     @Deprecated
getSensor(Context context, int sensorType)305     public static Sensor getSensor(Context context, int sensorType) {
306         SensorManager sensorManager =
307                 (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
308         if (sensorManager == null) {
309             throw new IllegalStateException("SensorService is not present in the system.");
310         }
311 
312         Sensor sensor = sensorManager.getDefaultSensor(sensorType);
313         if(sensor == null) {
314             throw new SensorNotSupportedException(sensorType);
315         }
316         return sensor;
317     }
318 
319     /**
320      * @return The maximum latency of a given sensor, on top of {@link #getMaxReportLatencyUs()}.
321      *
322      * NOTE: The latency is defined as the time between the event happens and the time the event is
323      * generated.
324      *
325      * - At time event_time (reported in the sensor event), the physical event happens
326      * - At time event_time + detection_latency, the physical event is detected and the event is
327      *   saved in the hardware fifo
328      * - At time event_time + detection_latency + report_latency, the event is reported through the
329      *   HAL
330      *
331      * Soon after that, the event is piped through the framework to the application. This time may
332      * vary depending on the CPU load. The time 'detection_latency' must be less than
333      * {@link #getSensorMaxDetectionLatencyNs(Sensor)}, and 'report_latency' must be less than
334      * {@link #getMaxReportLatencyUs()} passed through batch() at the HAL level.
335      */
336     // TODO: when all tests are moved to use the Sensor test framework, make this method non-static
getSensorMaxDetectionLatencyNs(Sensor sensor)337     public static long getSensorMaxDetectionLatencyNs(Sensor sensor) {
338         int reportLatencySec;
339         switch (sensor.getType()) {
340             case Sensor.TYPE_STEP_DETECTOR:
341                 reportLatencySec = 2;
342                 break;
343             case Sensor.TYPE_STEP_COUNTER:
344                 reportLatencySec = 10;
345                 break;
346             case Sensor.TYPE_SIGNIFICANT_MOTION:
347                 reportLatencySec = 10;
348                 break;
349             default:
350                 reportLatencySec = 0;
351         }
352         return TimeUnit.SECONDS.toNanos(reportLatencySec);
353     }
354 
355     @Override
toString()356     public String toString() {
357         return String.format(
358                 "Sensor='%s', SamplingRateOverloaded=%s, SamplingPeriod=%sus, "
359                         + "MaxReportLatency=%sus",
360                 mSensor,
361                 isSensorSamplingRateOverloaded(),
362                 mSamplingPeriodUs,
363                 mMaxReportLatencyUs);
364     }
365 
366     /**
367      * Return true if {@link #getRequestedSamplingPeriodUs()} is not one of
368      * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or
369      * {@link SensorManager#SENSOR_DELAY_NORMAL}.
370      */
isDelayRateTestable()371     private boolean isDelayRateTestable() {
372         return (mSamplingPeriodUs >= 0
373                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_GAME
374                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_UI
375                 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_NORMAL);
376     }
377 
isDeviceSuspendTest()378     public boolean isDeviceSuspendTest() {
379         return mIsDeviceSuspendTest;
380     }
381 }
382 
383