/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.hardware.cts.helpers; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.cts.helpers.sensoroperations.SensorOperation; import java.util.concurrent.TimeUnit; /* TODO: Refactor constructors into a builder */ /** * A class that encapsulates base environment information for the {@link SensorOperation}. * The environment is self contained and carries its state around all the sensor test framework. */ public class TestSensorEnvironment { /** * It represents the fraction of the expected sampling frequency, at which the sensor can * actually produce events. */ private static final float MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER = 0.9f; private final Context mContext; private final Sensor mSensor; private final boolean mSensorMightHaveMoreListeners; private final int mSamplingPeriodUs; private final int mMaxReportLatencyUs; private final boolean mIsDeviceSuspendTest; private final boolean mIsIntegrationTest; private final boolean mIsAutomotiveSpecificTest; /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param samplingPeriodUs The requested collection period for the sensor under test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) { this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param samplingPeriodUs The requested collection period for the sensor under test * @param maxReportLatencyUs The requested collection report latency for the sensor under test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment( Context context, int sensorType, int samplingPeriodUs, int maxReportLatencyUs) { this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs, maxReportLatencyUs); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load * @param samplingPeriodUs The requested collection period for the sensor under test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs) { this(context, sensorType, sensorMightHaveMoreListeners, samplingPeriodUs, 0 /* maxReportLatencyUs */); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load * @param samplingPeriodUs The requested collection period for the sensor under test * @param isAutomotiveSpecificTest Whether this is an automotive specific test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, boolean isAutomotiveSpecificTest) { this(context, getSensor(context, sensorType), sensorMightHaveMoreListeners, samplingPeriodUs, 0 /* maxReportLatencyUs */, false, false, isAutomotiveSpecificTest); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load * @param samplingPeriodUs The requested collection period for the sensor under test * @param maxReportLatencyUs The requested collection report latency for the sensor under test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs) { this(context, getSensor(context, sensorType), sensorMightHaveMoreListeners, samplingPeriodUs, maxReportLatencyUs); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensorType The type of the sensor under test * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load * @param isIntegrationTest Whether this is an integration test (more than one sensor actived) * @param samplingPeriodUs The requested collection period for the sensor under test * @param maxReportLatencyUs The requested collection report latency for the sensor under test * * @deprecated Use variants with {@link Sensor} objects. */ @Deprecated public TestSensorEnvironment( Context context, int sensorType, boolean sensorMightHaveMoreListeners, boolean isIntegrationTest, int samplingPeriodUs, int maxReportLatencyUs) { this(context, getSensor(context, sensorType), sensorMightHaveMoreListeners, isIntegrationTest, samplingPeriodUs, maxReportLatencyUs); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensor The sensor under test * @param samplingPeriodUs The requested collection period for the sensor under test * @param maxReportLatencyUs The requested collection report latency for the sensor under test */ public TestSensorEnvironment( Context context, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs) { this(context, sensor, false /* sensorMightHaveMoreListeners */, samplingPeriodUs, maxReportLatencyUs); } /** * Constructs an environment for sensor testing. * * @param context The context for the test * @param sensor The sensor under test * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this * usually implies that there are several listeners * requesting different sampling periods) * @param samplingPeriodUs The requested collection period for the sensor under test * @param maxReportLatencyUs The requested collection report latency for the sensor under test */ public TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs) { this(context, sensor, sensorMightHaveMoreListeners, samplingPeriodUs, maxReportLatencyUs, false /* isDeviceSuspendTest */); } public TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, boolean isIntegrationTest, int samplingPeriodUs, int maxReportLatencyUs) { this(context, sensor, sensorMightHaveMoreListeners, samplingPeriodUs, maxReportLatencyUs, false /* isDeviceSuspendTest */, isIntegrationTest, false /* isAutomotiveSpecificTest */); } public TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs, boolean isDeviceSuspendTest) { this(context, sensor, sensorMightHaveMoreListeners, samplingPeriodUs, maxReportLatencyUs, isDeviceSuspendTest, false /* isIntegrationTest */, false /* isAutomotiveSpecificTest */); } public TestSensorEnvironment( Context context, Sensor sensor, boolean sensorMightHaveMoreListeners, int samplingPeriodUs, int maxReportLatencyUs, boolean isDeviceSuspendTest, boolean isIntegrationTest, boolean isAutomotiveSpecificTest) { mContext = context; mSensor = sensor; mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners; mSamplingPeriodUs = samplingPeriodUs; mMaxReportLatencyUs = maxReportLatencyUs; mIsDeviceSuspendTest = isDeviceSuspendTest; mIsIntegrationTest = isIntegrationTest; mIsAutomotiveSpecificTest = isAutomotiveSpecificTest; } /** * @return The context instance associated with the test. */ public Context getContext() { return mContext; } /** * @return The sensor under test. */ public Sensor getSensor() { return mSensor; } /** * @return The requested collection rate in microseconds. */ public int getRequestedSamplingPeriodUs() { return mSamplingPeriodUs; } /** * @return The frequency equivalent to {@link #getRequestedSamplingPeriodUs()}. */ public double getFrequencyHz() { return SensorCtsHelper.getFrequency(mSamplingPeriodUs, TimeUnit.MICROSECONDS); } /** * @return A string representing the frequency equivalent to * {@link #getRequestedSamplingPeriodUs()}. */ public String getFrequencyString() { if (mSamplingPeriodUs == SensorManager.SENSOR_DELAY_FASTEST) { return "fastest"; } return String.format("%.2fhz", getFrequencyHz()); } /** * @return The requested collection max batch report latency in microseconds. */ public int getMaxReportLatencyUs() { return mMaxReportLatencyUs; } /** * Returns {@code true} if there might be other listeners of {@link #getSensor()} requesting * data at different sampling rates (the rates are unknown); false otherwise. */ public boolean isSensorSamplingRateOverloaded() { return mSensorMightHaveMoreListeners && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST; } /** * Convert the {@link #getRequestedSamplingPeriodUs()} into delay in microseconds. *

* The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does * not specify values for these flags. The rate is set to the max of * {@link Sensor#getMinDelay()} and the rate given. *

*/ public int getExpectedSamplingPeriodUs() { if (!isDelayRateTestable()) { throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]"); } int expectedSamplingPeriodUs = mSamplingPeriodUs; int sensorMaxDelay = mSensor.getMaxDelay(); if (sensorMaxDelay > 0) { expectedSamplingPeriodUs = Math.min(expectedSamplingPeriodUs, sensorMaxDelay); } return Math.max(expectedSamplingPeriodUs, mSensor.getMinDelay()); } /** * Calculate the maximum expected sampling period in us. * @return The maximum acceptable actual sampling period of this sensor. * For continuous sensors, this is higher than {@link #getExpectedSamplingPeriodUs()} * because sensors are allowed to run up to 10% slower than requested. * For sensors with other reporting modes, this is the maximum integer * {@link Integer#MAX_VALUE} as they can report no events for long * periods of time. */ public int getMaximumExpectedSamplingPeriodUs() { int sensorReportingMode = mSensor.getReportingMode(); if (sensorReportingMode != Sensor.REPORTING_MODE_CONTINUOUS) { return Integer.MAX_VALUE; } int expectedSamplingPeriodUs = getExpectedSamplingPeriodUs(); return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER); } /** * Calculate the allowed sensor start delay. * * CDD Section 7.3: * MUST report the first sensor sample within 400 milliseconds + 2 * sample_time of the * sensor being activated. It is acceptable for this sample to have an accuracy of 0. * * [CDD] Keep this updated with CDD. */ public long getAllowedSensorStartDelay() { return TimeUnit.MILLISECONDS.toMicros(400) + 2 * getMaximumExpectedSamplingPeriodUs(); } /** * @return The number of axes in the coordinate system of the sensor under test. */ public int getSensorAxesCount() { switch (mSensor.getType()) { case Sensor.TYPE_GYROSCOPE: return 3; default: throw new IllegalStateException("Axes count needs to be defined for sensor type: " + mSensor.getStringType()); } } /** * Get the default sensor for a given type. * * @deprecated Used for historical reasons, sensor tests must be written around Sensor objects, * so all sensors of a given type are exercised. */ @Deprecated public static Sensor getSensor(Context context, int sensorType) { SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); if (sensorManager == null) { throw new IllegalStateException("SensorService is not present in the system."); } Sensor sensor = sensorManager.getDefaultSensor(sensorType); if(sensor == null) { throw new SensorNotSupportedException(sensorType); } return sensor; } /** * @return The maximum latency of a given sensor, on top of {@link #getMaxReportLatencyUs()}. * * NOTE: The latency is defined as the time between the event happens and the time the event is * generated. * * - At time event_time (reported in the sensor event), the physical event happens * - At time event_time + detection_latency, the physical event is detected and the event is * saved in the hardware fifo * - At time event_time + detection_latency + report_latency, the event is reported through the * HAL * * Soon after that, the event is piped through the framework to the application. This time may * vary depending on the CPU load. The time 'detection_latency' must be less than * {@link #getSensorMaxDetectionLatencyNs(Sensor)}, and 'report_latency' must be less than * {@link #getMaxReportLatencyUs()} passed through batch() at the HAL level. */ // TODO: when all tests are moved to use the Sensor test framework, make this method non-static public static long getSensorMaxDetectionLatencyNs(Sensor sensor) { int reportLatencySec; switch (sensor.getType()) { case Sensor.TYPE_STEP_DETECTOR: reportLatencySec = 2; break; case Sensor.TYPE_STEP_COUNTER: reportLatencySec = 10; break; case Sensor.TYPE_SIGNIFICANT_MOTION: reportLatencySec = 10; break; default: reportLatencySec = 0; } return TimeUnit.SECONDS.toNanos(reportLatencySec); } @Override public String toString() { return String.format( "Sensor='%s', SamplingRateOverloaded=%s, SamplingPeriod=%sus, " + "MaxReportLatency=%sus", mSensor, isSensorSamplingRateOverloaded(), mSamplingPeriodUs, mMaxReportLatencyUs); } /** * Return true if {@link #getRequestedSamplingPeriodUs()} is not one of * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or * {@link SensorManager#SENSOR_DELAY_NORMAL}. */ private boolean isDelayRateTestable() { return (mSamplingPeriodUs >= 0 && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_GAME && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_UI && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_NORMAL); } public boolean isDeviceSuspendTest() { return mIsDeviceSuspendTest; } public boolean isIntegrationTest() { return mIsIntegrationTest; } public boolean isAutomotiveSpecificTest() { return mIsAutomotiveSpecificTest; } }