Add 200hz sensor tests and use maxDelay to make tests more lenient

Change-Id: I37a158418763048641d81bf0a6894fd479681224
diff --git a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
index cd6adb1..d33a108 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
@@ -89,6 +89,7 @@
     private static final int BATCHING_OFF = 0;
     private static final int BATCHING_5S = 5000000;
 
+    private static final int RATE_200HZ = 5000;
     private static final int RATE_100HZ = 10000;
     private static final int RATE_50HZ = 20000;
     private static final int RATE_25HZ = 40000;
@@ -144,6 +145,10 @@
         runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_100HZ, BATCHING_OFF);
     }
 
+    public void testAccelerometer_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testAccelerometer_50hz() throws Throwable {
         runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ, BATCHING_OFF);
     }
@@ -180,6 +185,10 @@
         runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
     }
 
+    public void testMagneticField_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testMagneticField_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_100HZ, BATCHING_OFF);
     }
@@ -222,6 +231,10 @@
     }
 
     @SuppressWarnings("deprecation")
+    public void testOrientation_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_200HZ, BATCHING_OFF);
+    }
+    @SuppressWarnings("deprecation")
     public void testOrientation_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_ORIENTATION, RATE_100HZ, BATCHING_OFF);
     }
@@ -270,6 +283,10 @@
         runSensorTest(Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
     }
 
+    public void testGyroscope_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testGyroscope_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_100HZ, BATCHING_OFF);
     }
@@ -310,6 +327,10 @@
         runSensorTest(Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
     }
 
+    public void testPressure_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testPressure_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_PRESSURE, RATE_100HZ, BATCHING_OFF);
     }
@@ -350,6 +371,10 @@
         runSensorTest(Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_OFF);
     }
 
+    public void testGravity_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testGravity_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_GRAVITY, RATE_100HZ, BATCHING_OFF);
     }
@@ -390,6 +415,11 @@
         runSensorTest(Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
                 BATCHING_OFF);
     }
+
+    public void testRotationVector_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testRotationVector_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
     }
@@ -431,6 +461,10 @@
                 BATCHING_OFF);
     }
 
+    public void testMagneticFieldUncalibrated_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testMagneticFieldUncalibrated_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_100HZ, BATCHING_OFF);
     }
@@ -473,6 +507,10 @@
                 BATCHING_OFF);
     }
 
+    public void testGameRotationVector_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testGameRotationVector_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
     }
@@ -515,6 +553,10 @@
                 BATCHING_OFF);
     }
 
+    public void testGyroscopeUncalibrated_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_200HZ, BATCHING_OFF);
+    }
+
     public void testGyroscopeUncalibrated_100hz() throws Throwable {
         runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_100HZ, BATCHING_OFF);
     }
@@ -557,41 +599,45 @@
                 BATCHING_OFF);
     }
 
-    public void  testGeomagneticRotationVector_100hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_100HZ, BATCHING_OFF);
+    public void  testLinearAcceleration_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_200HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_50hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_OFF);
+    public void  testLinearAcceleration_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_100HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_25hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_25HZ, BATCHING_OFF);
+    public void testLinearAcceleration_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_50HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_15hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_15HZ, BATCHING_OFF);
+    public void testLinearAcceleration_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_25HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_10hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_10HZ, BATCHING_OFF);
+    public void testLinearAcceleration_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_15HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_5hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_5HZ, BATCHING_OFF);
+    public void testLinearAcceleration_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_10HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_1hz() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_1HZ, BATCHING_OFF);
+    public void testLinearAcceleration_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_5HZ, BATCHING_OFF);
     }
 
-    public void testGeomagneticRotationVector_fastest_batching() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,
+    public void testLinearAcceleration_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_1HZ, BATCHING_OFF);
+    }
+
+    public void testLinearAcceleration_fastest_batching() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, SensorManager.SENSOR_DELAY_FASTEST,
                 BATCHING_5S);
     }
 
-    public void testGeomagneticRotationVector_50hz_batching() throws Throwable {
-        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_5S);
+    public void testLinearAcceleration_50hz_batching() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_50HZ, BATCHING_5S);
     }
 
     private void runSensorTest(int sensorType, int rateUs, int maxBatchReportLatencyUs)
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
index 4815688..b6704b6 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
@@ -22,6 +22,7 @@
 import android.hardware.cts.helpers.SensorTestInformation;
 import android.hardware.cts.helpers.SensorTestInformation.SensorReportingMode;
 import android.hardware.cts.helpers.TestSensorEvent;
+import android.util.Log;
 
 import junit.framework.Assert;
 
@@ -33,15 +34,17 @@
  */
 public class FrequencyVerification extends AbstractSensorVerification {
     public static final String PASSED_KEY = "frequency_passed";
+    private static final String LOG_TAG = FrequencyVerification.class.getSimpleName();
 
-    // lower threshold is (100 - 10)% expected
-    private static final int DEFAULT_LOWER_THRESHOLD = 10;
-    // upper threshold is (100 + 110)% expected
-    private static final int DEFAULT_UPPER_THRESHOLD = 110;
+    // Lowest acceptable frequency, as percentage of the requested one.
+    private static final int DEFAULT_LOWER_THRESHOLD = 90;
+    // Highest acceptable frequency, as percentage of the requested one.
+    private static final int DEFAULT_UPPER_THRESHOLD = 220;
 
-    private final double mExpected;
-    private final double mLowerThreshold;
-    private final double mUpperThreshold;
+    private final double mRequestedFrequencyHz;
+    private final double mLowerThresholdHz;
+    private final double mUpperThresholdHz;
+    private final String mSensorName;
 
     private long mMinTimestamp = 0;
     private long mMaxTimestamp = 0;
@@ -51,15 +54,15 @@
      * Construct a {@link FrequencyVerification}.
      *
      * @param expected the expected frequency in Hz.
-     * @param lowerTheshold the lower threshold in Hz. {@code expected - lower} should be the
-     * slowest acceptable frequency of the sensor.
-     * @param upperThreshold the upper threshold in Hz. {@code expected + upper} should be the
-     * fastest acceptable frequency of the sensor.
+     * @param lowerTheshold Lowest acceptable frequency Hz.
+     * @param upperThreshold Highest acceptable frequency Hz.
      */
-    public FrequencyVerification(double expected, double lowerTheshold, double upperThreshold) {
-        mExpected = expected;
-        mLowerThreshold = lowerTheshold;
-        mUpperThreshold = upperThreshold;
+    public FrequencyVerification(double expected, double lowerTheshold, double upperThreshold,
+        String sensorName) {
+        mRequestedFrequencyHz = expected;
+        mLowerThresholdHz = lowerTheshold;
+        mUpperThresholdHz = upperThreshold;
+        mSensorName = sensorName;
     }
 
     /**
@@ -75,13 +78,38 @@
             return null;
         }
 
-        // Expected frequency in Hz
-        double expected = SensorCtsHelper.getFrequency(SensorCtsHelper.getDelay(sensor, rateUs),
-                TimeUnit.MICROSECONDS);
-        // Expected frequency * threshold percentage
-        double lowerThreshold = expected * DEFAULT_LOWER_THRESHOLD / 100;
-        double upperThreshold = expected * DEFAULT_UPPER_THRESHOLD / 100;
-        return new FrequencyVerification(expected, lowerThreshold, upperThreshold);
+        Log.i(LOG_TAG, String.format("Preparing frequency test for \"%s\" for which "
+                + "minDelay=%dus and maxDelay=%dus",
+                sensor.getName(), sensor.getMinDelay(), sensor.getMaxDelay()));
+        double maxDelayUs = sensor.getMaxDelay();
+        if (maxDelayUs <= 0) {
+            // This sensor didn't report its maxDelay.
+            // It might be only capable of producing its max rate.
+            // Do as if it reported its minDelay as its maxDelay.
+            Log.w(LOG_TAG, "This sensor (" + sensor.getName() + ") didn't report its maxDelay."
+                    + "Please update it in the sensor HAL to avoid failures in coming "
+                    + "android releases.");
+            maxDelayUs = sensor.getMinDelay();
+        }
+
+        // Convert the rateUs parameter into a delay in microseconds and rate in Hz.
+        double delayUs = SensorCtsHelper.getDelay(sensor, rateUs);
+        double requestedFrequencyHz = SensorCtsHelper.getFrequency(
+            delayUs, TimeUnit.MICROSECONDS);
+
+        // When rateUs > maxDelay, the sensor can do as if we requested maxDelay.
+        double upperExpectedHz = SensorCtsHelper.getFrequency(
+                Math.min(delayUs, maxDelayUs), TimeUnit.MICROSECONDS);
+        // When rateUs < minDelay, the sensor can do as if we requested minDelay
+        double lowerExpectedHz = SensorCtsHelper.getFrequency(
+                Math.max(delayUs, sensor.getMinDelay()), TimeUnit.MICROSECONDS);
+
+        // Set the pass thresholds based on default multipliers.
+        double lowerThresholdHz = lowerExpectedHz * DEFAULT_LOWER_THRESHOLD / 100;
+        double upperThresholdHz = upperExpectedHz * DEFAULT_UPPER_THRESHOLD / 100;
+
+        return new FrequencyVerification(requestedFrequencyHz, lowerThresholdHz, upperThresholdHz,
+            sensor.getName());
     }
 
     /**
@@ -97,18 +125,22 @@
             return;
         }
 
-        double frequency = SensorCtsHelper.getFrequency(
+        double measuredFrequencyHz = SensorCtsHelper.getFrequency(
                 ((double) (mMaxTimestamp - mMinTimestamp)) / (mCount - 1), TimeUnit.NANOSECONDS);
-        boolean failed = (frequency <= mExpected - mLowerThreshold
-                || frequency >= mExpected + mUpperThreshold);
+        boolean failed = (measuredFrequencyHz <= mLowerThresholdHz
+                || measuredFrequencyHz >= mUpperThresholdHz);
 
-        stats.addValue(SensorStats.FREQUENCY_KEY, frequency);
+        stats.addValue(SensorStats.FREQUENCY_KEY, measuredFrequencyHz);
         stats.addValue(PASSED_KEY, !failed);
+        String resultString = String.format("Requested \"" + mSensorName + "\" at %.2fHz "
+                + "(expecting between %.2fHz and %.2fHz, measured %.2fHz)",
+                mRequestedFrequencyHz, mLowerThresholdHz, mUpperThresholdHz, measuredFrequencyHz);
 
         if (failed) {
-            Assert.fail(String.format("Frequency out of range: frequency=%.2fHz "
-                    + "(expected (%.2f-%.2fHz, %.2f+%.2fHz))", frequency, mExpected,
-                    mLowerThreshold, mExpected, mUpperThreshold));
+            Log.e(LOG_TAG, "Frequency test FAIL: " + resultString);
+            Assert.fail(String.format("Frequency out of range: " + resultString));
+        } else {
+            Log.i(LOG_TAG, "Frequency test pass: " + resultString);
         }
     }
 
@@ -117,7 +149,8 @@
      */
     @Override
     public FrequencyVerification clone() {
-        return new FrequencyVerification(mExpected, mLowerThreshold, mUpperThreshold);
+        return new FrequencyVerification(mRequestedFrequencyHz, mLowerThresholdHz,
+            mUpperThresholdHz, mSensorName);
     }
 
     /**
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
index cec09a5..82d93e5 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
@@ -33,22 +33,22 @@
         long[] timestamps = {0, 1000000, 2000000, 3000000, 4000000};  // 1000Hz
 
         SensorStats stats = new SensorStats();
-        ISensorVerification verification = getVerification(1000.0, 1.0, 1.0, timestamps);
+        ISensorVerification verification = getVerification(1000.0, 999.0, 1001.0, timestamps);
         verification.verify(stats);
         verifyStats(stats, true, 1000.0);
 
         stats = new SensorStats();
-        verification = getVerification(950.0, 100.0, 100.0, timestamps);
+        verification = getVerification(950.0, 850.0, 1050.0, timestamps);
         verification.verify(stats);
         verifyStats(stats, true, 1000.0);
 
         stats = new SensorStats();
-        verification = getVerification(1050.0, 100.0, 100.0, timestamps);
+        verification = getVerification(1050.0, 950.0, 1150.0, timestamps);
         verification.verify(stats);
         verifyStats(stats, true, 1000.0);
 
         stats = new SensorStats();
-        verification = getVerification(950.0, 100.0, 25.0, timestamps);
+        verification = getVerification(950.0, 850.0, 975.0, timestamps);
         try {
             verification.verify(stats);
             fail("Expected an AssertionError");
@@ -58,7 +58,7 @@
         verifyStats(stats, false, 1000.0);
 
         stats = new SensorStats();
-        verification = getVerification(1050.0, 25.0, 100.0, timestamps);
+        verification = getVerification(1050.0, 1025.0, 1150.0, timestamps);
         try {
             verification.verify(stats);
             fail("Expected an AssertionError");
@@ -71,7 +71,7 @@
     private ISensorVerification getVerification(double expected, double lowerThreshold,
             double upperThreshold, long ... timestamps) {
         ISensorVerification verification = new FrequencyVerification(expected, lowerThreshold,
-                upperThreshold);
+                upperThreshold, "Test sensor");
         for (long timestamp : timestamps) {
             verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
         }