CameraITS: Test ZSL EE and NR modes

Modify reprocess EE test to test ZSL mode.

Modify NR test and reprocess NR test to test ZSL and MINIMAL modes.

Bug: 22266686
Change-Id: I554ea604223bd1d6fc2b541d8e51a9b8b62a8c78
diff --git a/apps/CameraITS/pymodules/its/caps.py b/apps/CameraITS/pymodules/its/caps.py
index b6d398f..95f19d9 100644
--- a/apps/CameraITS/pymodules/its/caps.py
+++ b/apps/CameraITS/pymodules/its/caps.py
@@ -307,6 +307,35 @@
     return props.has_key("android.request.availableCapabilities") and \
            4 in props["android.request.availableCapabilities"]
 
+def noise_reduction_mode(props, mode):
+    """Returns whether a device supports the noise reduction mode.
+
+    Args:
+        props: Camera properties objects.
+        mode: Integer, indicating the noise reduction mode to check for
+              availability.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key(
+            "android.noiseReduction.availableNoiseReductionModes") and mode \
+            in props["android.noiseReduction.availableNoiseReductionModes"];
+
+def edge_mode(props, mode):
+    """Returns whether a device supports the edge mode.
+
+    Args:
+        props: Camera properties objects.
+        mode: Integer, indicating the edge mode to check for availability.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key(
+            "android.edge.availableEdgeModes") and mode \
+            in props["android.edge.availableEdgeModes"];
+
 class __UnitTest(unittest.TestCase):
     """Run a suite of unit tests on this module.
     """
diff --git a/apps/CameraITS/tests/scene1/test_param_noise_reduction.py b/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
index f5176a7..27da8fc 100644
--- a/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
+++ b/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
@@ -45,7 +45,8 @@
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
         its.caps.skip_unless(its.caps.compute_target_exposure(props) and
-                             its.caps.per_frame_control(props))
+                             its.caps.per_frame_control(props) and
+                             its.caps.noise_reduction_mode(props, 0))
 
         # NR mode 0 with low gain
         e, s = its.target.get_target_exposure_combos(cam)["minSensitivity"]
@@ -62,37 +63,51 @@
             ref_variance.append(its.image.compute_image_variances(tile)[0])
         print "Ref variances:", ref_variance
 
-        for i in range(3):
-            # NR modes 0, 1, 2 with high gain
+        # NR modes 0, 1, 2, 3, 4 with high gain
+        for mode in range(5):
+            # Skip unavailable modes
+            if not its.caps.noise_reduction_mode(props, mode):
+                nr_modes_reported.append(mode)
+                for channel in range(3):
+                    variances[channel].append(0)
+                continue;
+
             e, s = its.target.get_target_exposure_combos(cam)["maxSensitivity"]
             req = its.objects.manual_capture_request(s, e)
-            req["android.noiseReduction.mode"] = i
+            req["android.noiseReduction.mode"] = mode
             cap = cam.do_capture(req)
             nr_modes_reported.append(
                     cap["metadata"]["android.noiseReduction.mode"])
             its.image.write_image(
                     its.image.convert_capture_to_rgb_image(cap),
-                    "%s_high_gain_nr=%d.jpg" % (NAME, i))
+                    "%s_high_gain_nr=%d.jpg" % (NAME, mode))
             planes = its.image.convert_capture_to_planes(cap)
             for j in range(3):
                 img = planes[j]
                 tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
                 variance = its.image.compute_image_variances(tile)[0]
                 variances[j].append(variance / ref_variance[j])
-        print "Variances with NR mode [0,1,2]:", variances
+        print "Variances with NR mode [0,1,2,3,4]:", variances
 
     # Draw a plot.
     for j in range(3):
-        pylab.plot(range(3), variances[j], "rgb"[j])
+        pylab.plot(range(5), variances[j], "rgb"[j])
     matplotlib.pyplot.savefig("%s_plot_variances.png" % (NAME))
 
-    assert(nr_modes_reported == [0,1,2])
+    assert(nr_modes_reported == [0,1,2,3,4])
 
     # Check that the variance of the NR=0 image is higher than for the
     # NR=1 and NR=2 images.
     for j in range(3):
-        for i in range(1,3):
-            assert(variances[j][i] < variances[j][0])
+        for mode in [1,2]:
+            if its.caps.noise_reduction_mode(props, mode):
+                assert(variances[j][mode] < variances[j][0])
+                # Variance of MINIMAL should be higher than for FAST, HQ
+                if its.caps.noise_reduction_mode(props, 3):
+                    assert(variances[j][mode] < variances[j][3])
+                # Variance of ZSL should be higher than for FAST, HQ
+                if its.caps.noise_reduction_mode(props, 4):
+                    assert(variances[j][mode] < variances[j][4])
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py b/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
index e9240ba..c2657c7 100644
--- a/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
+++ b/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
@@ -42,9 +42,13 @@
 
         its.caps.skip_unless(its.caps.compute_target_exposure(props) and
                              its.caps.per_frame_control(props) and
+                             its.caps.noise_reduction_mode(props, 0) and
                              (its.caps.yuv_reprocess(props) or
                               its.caps.private_reprocess(props)))
 
+        # If reprocessing is supported, ZSL NR mode must be avaiable.
+        assert(its.caps.noise_reduction_mode(props, 4))
+
         reprocess_formats = []
         if (its.caps.yuv_reprocess(props)):
             reprocess_formats.append("yuv")
@@ -73,8 +77,14 @@
             ref_variance = its.image.compute_image_variances(tile)
             print "Ref variances:", ref_variance
 
-            for nr_mode in range(3):
-                # NR modes 0, 1, 2 with high gain
+            for nr_mode in range(5):
+                # Skipp unavailable modes
+                if not its.caps.noise_reduction_mode(props, nr_mode):
+                    nr_modes_reported.append(nr_mode)
+                    variances.append(0)
+                    continue
+
+                # NR modes with high gain
                 e, s = its.target.get_target_exposure_combos(cam) \
                     ["maxSensitivity"]
                 req = its.objects.manual_capture_request(s, e)
@@ -91,21 +101,31 @@
                 variance = its.image.compute_image_variances(tile)
                 variances.append(
                     [variance[chan] / ref_variance[chan] for chan in range(3)])
-            print "Variances with NR mode [0,1,2]:", variances
+            print "Variances with NR mode [0,1,2,3,4]:", variances
 
             # Draw a plot.
-            for nr_mode in range(3):
-                pylab.plot(range(3), variances[nr_mode], "rgb"[nr_mode])
+            for nr_mode in range(5):
+                if not its.caps.noise_reduction_mode(props, nr_mode):
+                    continue
+                pylab.plot(range(3), variances[nr_mode], "rgbcm"[nr_mode])
             matplotlib.pyplot.savefig("%s_plot_%s_variances.png" %
                                       (NAME, reprocess_format))
 
-            assert(nr_modes_reported == [0,1,2])
+            assert(nr_modes_reported == [0,1,2,3,4]
 
-            # Check that the variance of the NR=0 image is higher than for the
-            # NR=1 and NR=2 images.
-            for j in range(3):
-                for i in range(1,3):
-                    assert(variances[i][j] < variances[0][j])
+            # Check that the variances of the NR=0 and NR=3 and NR=4 images are
+            # higher than for the NR=1 and NR=2 images.
+            for channel in range(3):
+                for nr_mode in [1, 2]:
+                    if its.caps.noise_reduction_mode(props, nr_mode):
+                        assert(variances[nr_mode][channel] <
+                               variances[0][channel])
+                        if its.caps.noise_reduction_mode(props, 3):
+                            assert(variances[nr_mode][channel] <
+                                   variances[3][channel])
+                        if its.caps.noise_reduction_mode(props, 4):
+                            assert(variances[nr_mode][channel] <
+                                   variances[4][channel])
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
index 1966d9e..77208e7 100644
--- a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
@@ -90,9 +90,13 @@
 
         its.caps.skip_unless(its.caps.read_3a(props) and
                              its.caps.per_frame_control(props) and
+                             its.caps.edge_mode(props, 0) and
                              (its.caps.yuv_reprocess(props) or
                               its.caps.private_reprocess(props)))
 
+        # If reprocessing is supported, ZSL EE mode must be avaiable.
+        assert(its.caps.edge_mode(props, 3))
+
         reprocess_formats = []
         if (its.caps.yuv_reprocess(props)):
             reprocess_formats.append("yuv")
@@ -108,13 +112,18 @@
         # Get the sharpness for each edge mode for regular requests
         sharpness_regular = []
         edge_mode_reported_regular = []
-        for edge_mode in range(3):
+        for edge_mode in range(4):
+            # Skip unavailable modes
+            if not its.caps.edge_mode(props, edge_mode):
+                edge_mode_reported_regular.append(edge_mode)
+                sharpness_regular.append(0)
+                continue
             ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface)
             edge_mode_reported_regular.append(ret["edge_mode"])
             sharpness_regular.append(ret["sharpness"])
 
         print "Reported edge modes:", edge_mode_reported_regular
-        print "Sharpness with EE mode [0,1,2]:", sharpness_regular
+        print "Sharpness with EE mode [0,1,2,3]:", sharpness_regular
 
         # Get the sharpness for each reprocess format and edge mode for
         # reprocess requests.
@@ -125,7 +134,13 @@
             # List of sharpness
             sharpnesses = []
             edge_mode_reported = []
-            for edge_mode in range(3):
+            for edge_mode in range(4):
+                # Skip unavailable modes
+                if not its.caps.edge_mode(props, edge_mode):
+                    edge_mode_reported.append(edge_mode)
+                    sharpnesses.append(0)
+                    continue
+
                 ret = test_edge_mode(cam, edge_mode, s, e, fd, out_surface,
                     reprocess_format)
                 edge_mode_reported.append(ret["edge_mode"])
@@ -135,24 +150,31 @@
             edge_mode_reported_reprocess.append(edge_mode_reported)
 
             print "Reported edge modes:", edge_mode_reported
-            print "Sharpness with EE mode [0,1,2] for %s reprocess:" % \
+            print "Sharpness with EE mode [0,1,2,3] for %s reprocess:" % \
                 (reprocess_format) , sharpnesses
 
-        # Verify the results
-        assert(edge_mode_reported_regular == [0,1,2])
-        assert(sharpness_regular[1] >
-            sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
-        assert(sharpness_regular[2] >
-            sharpness_regular[0] * (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
+        # Verify reported modes for regular results
+        assert(edge_mode_reported_regular == [0,1,2,3])
+        # Verify the images for all modes are not too blurrier than OFF.
+        for edge_mode in [1, 2, 3]:
+            if its.caps.edge_mode(props, edge_mode):
+                assert(sharpness_regular[edge_mode] >
+                    sharpness_regular[0] *
+                    (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF))
+        # Verify the image for ZSL are not too sharper than OFF
+        assert(sharpness_regular[3] <
+                sharpness_regular[0] * (1.0 + THRESHOLD_RELATIVE_SHARPNESS_DIFF))
 
-        # Verify the reprocess
+        # Verify sharpness of reprocess captures are similar to sharpness of
+        # regular captures.
         for reprocess_format in range(len(reprocess_formats)):
-            assert(edge_mode_reported_reprocess[reprocess_format] == [0,1,2])
-            for edge_mode in range(3):
-                assert(sharpnesses_reprocess[reprocess_format][edge_mode] >=
-                    (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF) *
-                    sharpnesses_reprocess[reprocess_format][0] *
-                    sharpness_regular[edge_mode] / sharpness_regular[0])
+            assert(edge_mode_reported_reprocess[reprocess_format] == [0,1,2,3])
+            for edge_mode in range(4):
+                if its.caps.edge_mode(props, edge_mode):
+                    assert(sharpnesses_reprocess[reprocess_format][edge_mode] >=
+                        (1.0 - THRESHOLD_RELATIVE_SHARPNESS_DIFF) *
+                        sharpnesses_reprocess[reprocess_format][0] *
+                        sharpness_regular[edge_mode] / sharpness_regular[0])
 
 if __name__ == '__main__':
     main()