Camera: Test ZERO_SHUTTER_LAG modes

Test that ZERO_SHUTTER_LAG edge enhancement and noise reduction
modes are supported by camera devices that support reprocessing,
and they are the default modes for ZSL template.

Bug: 22266686
Change-Id: Ibf53107b3a91cbbf81ea470dfe476782c4d7c2c2
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 189d3cd..d71acd6 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1461,6 +1461,11 @@
             }
         }
 
+        // Edge enhancement and noise reduction modes
+        boolean supportReprocessing =
+                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING) ||
+                availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
+
         if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
             // Not enforce high quality here, as some devices may not effectively have high quality
             // mode.
@@ -1513,7 +1518,23 @@
                             request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
                 }
             }
+        } else if (template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG && supportReprocessing) {
+            mCollector.expectKeyValueEquals(request, EDGE_MODE,
+                    CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG);
+            mCollector.expectKeyValueEquals(request, NOISE_REDUCTION_MODE,
+                    CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
+        } else {
+            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
+                mCollector.expectKeyValueNotNull(request, EDGE_MODE);
+            }
 
+            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
+                mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
+            }
+        }
+
+        // Tone map and lens shading modes.
+        if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
             mCollector.expectEquals("Tonemap mode must be present in request if " +
                             "available tonemap modes are present in metadata, and vice-versa.",
                     mStaticInfo.areKeysAvailable(CameraCharacteristics.
@@ -1540,14 +1561,6 @@
                             STATISTICS_LENS_SHADING_MAP_MODE_ON);
             }
         } else {
-            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
-                mCollector.expectKeyValueNotNull(request, EDGE_MODE);
-            }
-
-            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
-                mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
-            }
-
             if (mStaticInfo.areKeysAvailable(TONEMAP_MODE)) {
                 mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
                         CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index e8a70f0..da083a6 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -23,6 +23,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.cts.helpers.CameraErrorCollector;
 import android.hardware.camera2.params.BlackLevelPattern;
 import android.hardware.camera2.params.ColorSpaceTransform;
@@ -544,58 +545,83 @@
                     c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
             Integer maxNumInputStreams =
                     c.get(CameraCharacteristics.REQUEST_MAX_NUM_INPUT_STREAMS);
+            int[] availableEdgeModes = c.get(CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES);
+            int[] availableNoiseReductionModes = c.get(
+                    CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES);
 
             int[] inputFormats = configs.getInputFormats();
 
-            assertFalse("Doesn't support reprocessing but report input format: " +
-                    Arrays.toString(inputFormats), !supportYUV && !supportOpaque &&
-                    inputFormats.length > 0);
+            boolean supportZslEdgeMode = false;
+            boolean supportZslNoiseReductionMode = false;
 
-            assertFalse("Doesn't support reprocessing but max number of input stream is " +
-                    maxNumInputStreams, !supportYUV && !supportOpaque &&
-                    maxNumInputStreams != null && maxNumInputStreams != 0);
+            if (availableEdgeModes != null) {
+                supportZslEdgeMode = Arrays.asList(CameraTestUtils.toObject(availableEdgeModes)).
+                        contains(CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG);
+            }
+
+            if (availableNoiseReductionModes != null) {
+                supportZslNoiseReductionMode = Arrays.asList(
+                        CameraTestUtils.toObject(availableNoiseReductionModes)).contains(
+                        CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
+            }
 
             if (supportYUV || supportOpaque) {
-                assertTrue("Support reprocessing but max number of input stream is " +
+                mCollector.expectTrue("Support reprocessing but max number of input stream is " +
                         maxNumInputStreams, maxNumInputStreams != null && maxNumInputStreams > 0);
+                mCollector.expectTrue("Support reprocessing but EDGE_MODE_ZERO_SHUTTER_LAG is " +
+                        "not supported", supportZslEdgeMode);
+                mCollector.expectTrue("Support reprocessing but " +
+                        "NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG is not supported",
+                        supportZslNoiseReductionMode);
 
                 // Verify mandatory input formats are supported
-                assertTrue("YUV_420_888 input must be supported for YUV reprocessing",
+                mCollector.expectTrue("YUV_420_888 input must be supported for YUV reprocessing",
                         !supportYUV || arrayContains(inputFormats, ImageFormat.YUV_420_888));
-                assertTrue("PRIVATE input must be supported for OPAQUE reprocessing",
+                mCollector.expectTrue("PRIVATE input must be supported for OPAQUE reprocessing",
                         !supportOpaque || arrayContains(inputFormats, ImageFormat.PRIVATE));
 
                 // max capture stall must be reported if one of the reprocessing is supported.
                 final int MAX_ALLOWED_STALL_FRAMES = 4;
                 Integer maxCaptureStall = c.get(CameraCharacteristics.REPROCESS_MAX_CAPTURE_STALL);
-                assertTrue("max capture stall must be non-null and no larger than "
+                mCollector.expectTrue("max capture stall must be non-null and no larger than "
                         + MAX_ALLOWED_STALL_FRAMES,
                         maxCaptureStall != null && maxCaptureStall <= MAX_ALLOWED_STALL_FRAMES);
 
                 for (int input : inputFormats) {
                     // Verify mandatory output formats are supported
                     int[] outputFormats = configs.getValidOutputFormatsForInput(input);
-                    assertTrue("YUV_420_888 output must be supported for reprocessing",
+                    mCollector.expectTrue("YUV_420_888 output must be supported for reprocessing",
                             arrayContains(outputFormats, ImageFormat.YUV_420_888));
-                    assertTrue("JPEG output must be supported for reprocessing",
+                    mCollector.expectTrue("JPEG output must be supported for reprocessing",
                             arrayContains(outputFormats, ImageFormat.JPEG));
 
                     // Verify camera can output the reprocess input formats and sizes.
                     Size[] inputSizes = configs.getInputSizes(input);
                     Size[] outputSizes = configs.getOutputSizes(input);
                     Size[] highResOutputSizes = configs.getHighResolutionOutputSizes(input);
-                    assertTrue("no input size supported for format " + input,
+                    mCollector.expectTrue("no input size supported for format " + input,
                             inputSizes.length > 0);
-                    assertTrue("no output size supported for format " + input,
+                    mCollector.expectTrue("no output size supported for format " + input,
                             outputSizes.length > 0);
 
                     for (Size inputSize : inputSizes) {
-                        assertTrue("Camera must be able to output the supported reprocessing " +
-                                "input size",
+                        mCollector.expectTrue("Camera must be able to output the supported " +
+                                "reprocessing input size",
                                 arrayContains(outputSizes, inputSize) ||
                                 arrayContains(highResOutputSizes, inputSize));
                     }
                 }
+            } else {
+                mCollector.expectTrue("Doesn't support reprocessing but report input format: " +
+                        Arrays.toString(inputFormats), inputFormats.length == 0);
+                mCollector.expectTrue("Doesn't support reprocessing but max number of input " +
+                        "stream is " + maxNumInputStreams,
+                        maxNumInputStreams == null || maxNumInputStreams == 0);
+                mCollector.expectTrue("Doesn't support reprocessing but " +
+                        "EDGE_MODE_ZERO_SHUTTER_LAG is supported", !supportZslEdgeMode);
+                mCollector.expectTrue("Doesn't support reprocessing but " +
+                        "NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG is supported",
+                        !supportZslNoiseReductionMode);
             }
         }
     }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index 6242776..e774738 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -979,7 +979,6 @@
      *   2. NOISE_REDUCTION_MODE
      *   3. REPROCESS_EFFECTIVE_EXPOSURE_FACTOR (only for YUV reprocess)
      */
-
     private void testReprocessRequestKeys(String cameraId, Size inputSize, int inputFormat,
             Size reprocessOutputSize, int reprocessOutputFormat) throws Exception {
         if (VERBOSE) {
@@ -989,10 +988,13 @@
         }
 
         final Integer[] EDGE_MODES = {CaptureRequest.EDGE_MODE_FAST,
-                CaptureRequest.EDGE_MODE_HIGH_QUALITY, CaptureRequest.EDGE_MODE_OFF};
+                CaptureRequest.EDGE_MODE_HIGH_QUALITY, CaptureRequest.EDGE_MODE_OFF,
+                CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG};
         final Integer[] NR_MODES = {CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY,
-                CaptureRequest.NOISE_REDUCTION_MODE_OFF, CaptureRequest.NOISE_REDUCTION_MODE_FAST};
-        final Float[] EFFECTIVE_EXP_FACTORS = {null, 1.0f, 2.5f};
+                CaptureRequest.NOISE_REDUCTION_MODE_OFF,
+                CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG,
+                CaptureRequest.NOISE_REDUCTION_MODE_FAST};
+        final Float[] EFFECTIVE_EXP_FACTORS = {null, 1.0f, 2.5f, 4.0f};
         int numFrames = EDGE_MODES.length;
 
         try {