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