Camera2: Improve testing for devices supporting long exposures

- Use correct timeout in CaptureRequestTest aeManualControlTest
- Set up a repeating request to keep pipeline fed in aeManualControlTest
- Minor other cleanup for time units
- Reduce max number of sensitivity steps by 2x

With a 4-second maximum exposure, aeManualControlTest takes 3.5 minutes with
these changes.

Test: Updated CTS test passes on device with long exposure, in reasonable time
Bug: 38212789
Change-Id: I648662e3270884151f9e6065464508cf63333527
diff --git a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
index 3bcccd2..8c7e342 100644
--- a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
@@ -595,7 +595,7 @@
         final float THRESHOLD_MAX_MIN_DIFF = 0.3f;
         final float THRESHOLD_MAX_MIN_RATIO = 2.0f;
         final int NUM_STEPS = 5;
-        final long EXPOSURE_TIME_NS = 2000000; // 2 seconds
+        final long EXPOSURE_TIME_NS = 2000000; // 2 ms
         final int RGB_CHANNELS = 3;
 
         mCameraIterable.forEachCamera(/*fullHwLevel*/false, new CameraBlock() {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 66756e1..11b7b5f 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -62,7 +62,7 @@
     private static final int NUM_FRAMES_VERIFIED = 15;
     private static final int NUM_FACE_DETECTION_FRAMES_VERIFIED = 60;
     /** 30ms exposure time must be supported by full capability devices. */
-    private static final long DEFAULT_EXP_TIME_NS = 30000000L;
+    private static final long DEFAULT_EXP_TIME_NS = 30000000L; // 30ms
     private static final int DEFAULT_SENSITIVITY = 100;
     private static final int RGGB_COLOR_CHANNEL_COUNT = 4;
     private static final int MAX_SHADING_MAP_SIZE = 64 * 64 * RGGB_COLOR_CHANNEL_COUNT;
@@ -74,7 +74,7 @@
     private static final float EXPOSURE_TIME_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
     private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
     private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
-    private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 16;
+    private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 8;
     private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
     private static final int NUM_RESULTS_WAIT_TIMEOUT = 100;
     private static final int NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY = 8;
@@ -1624,34 +1624,43 @@
             throws Exception {
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-
-        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
         configurePreviewOutput(requestBuilder);
+
+        // Warm up pipeline for more accurate timing
+        SimpleCaptureCallback warmupListener =  new SimpleCaptureCallback();
+        mSession.setRepeatingRequest(requestBuilder.build(), warmupListener, mHandler);
+        warmupListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+
+        // Do manual captures
+        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
         SimpleCaptureCallback listener =  new SimpleCaptureCallback();
 
-        long[] expTimes = getExposureTimeTestValues();
+        long[] expTimesNs = getExposureTimeTestValues();
         int[] sensitivities = getSensitivityTestValues();
         // Submit single request at a time, then verify the result.
-        for (int i = 0; i < expTimes.length; i++) {
+        for (int i = 0; i < expTimesNs.length; i++) {
             for (int j = 0; j < sensitivities.length; j++) {
                 if (VERBOSE) {
                     Log.v(TAG, "Camera " + mCamera.getId() + ": Testing sensitivity "
-                            + sensitivities[j] + ", exposure time " + expTimes[i] + "ns");
+                            + sensitivities[j] + ", exposure time " + expTimesNs[i] + "ns");
                 }
 
-                changeExposure(requestBuilder, expTimes[i], sensitivities[j]);
+                changeExposure(requestBuilder, expTimesNs[i], sensitivities[j]);
                 mSession.capture(requestBuilder.build(), listener, mHandler);
 
-                // make sure timeout is long enough for long exposure time
-                long timeout = WAIT_FOR_RESULT_TIMEOUT_MS + expTimes[i];
-                CaptureResult result = listener.getCaptureResult(timeout);
-                long resultExpTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
+                // make sure timeout is long enough for long exposure time - add a 2x safety margin
+                // to exposure time
+                long timeoutMs = WAIT_FOR_RESULT_TIMEOUT_MS + 2 * expTimesNs[i] / 1000000;
+                CaptureResult result = listener.getCaptureResult(timeoutMs);
+                long resultExpTimeNs = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
                 int resultSensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
-                validateExposureTime(expTimes[i], resultExpTime);
+                validateExposureTime(expTimesNs[i], resultExpTimeNs);
                 validateSensitivity(sensitivities[j], resultSensitivity);
                 validateFrameDurationForCapture(result);
             }
         }
+        mSession.stopRepeating();
+
         // TODO: Add another case to test where we can submit all requests, then wait for
         // results, which will hide the pipeline latency. this is not only faster, but also
         // test high speed per frame control and synchronization.
@@ -2413,7 +2422,7 @@
 
     /**
      * Get the exposure time array that contains multiple exposure time steps in
-     * the exposure time range.
+     * the exposure time range, in nanoseconds.
      */
     private long[] getExposureTimeTestValues() {
         long[] testValues = new long[DEFAULT_NUM_EXPOSURE_TIME_STEPS + 1];