Merge "CTS test for runtime permission grants" into mnc-dev
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index bc77a62..82346ec 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -211,12 +211,20 @@
     set_filter_off_or_fast_if_possible(props, req,
         "android.colorCorrection.availableAberrationModes",
         "android.colorCorrection.aberrationMode")
-    set_filter_off_or_fast_if_possible(props, req,
-        "android.hotPixel.availableHotPixelModes",
-        "android.hotPixel.mode")
-    set_filter_off_or_fast_if_possible(props, req,
-        "android.edge.availableEdgeModes",
-        "android.edge.mode")
+    if props.has_key("android.request.availableCharacteristicsKeys"):
+        hot_pixel_modes = 393217 in props["android.request.availableCharacteristicsKeys"]
+        edge_modes = 196610 in props["android.request.availableCharacteristicsKeys"]
+    if props.has_key("android.request.availableRequestKeys"):
+        hot_pixel_mode = 393216 in props["android.request.availableRequestKeys"]
+        edge_mode = 196608 in props["android.request.availableRequestKeys"]
+    if hot_pixel_modes and hot_pixel_mode:
+        set_filter_off_or_fast_if_possible(props, req,
+            "android.hotPixel.availableHotPixelModes",
+            "android.hotPixel.mode")
+    if edge_modes and edge_mode:
+        set_filter_off_or_fast_if_possible(props, req,
+            "android.edge.availableEdgeModes",
+            "android.edge.mode")
 
 def get_fastest_manual_capture_settings(props):
     """Return a capture request and format spec for the fastest capture.
diff --git a/apps/CameraITS/tests/scene0/test_metadata.py b/apps/CameraITS/tests/scene0/test_metadata.py
index b4ca4cb..375a6af 100644
--- a/apps/CameraITS/tests/scene0/test_metadata.py
+++ b/apps/CameraITS/tests/scene0/test_metadata.py
@@ -48,16 +48,19 @@
     check('props["android.info.supportedHardwareLevel"] is not None')
     check('props["android.info.supportedHardwareLevel"] in [0,1,2]')
     full = getval('props["android.info.supportedHardwareLevel"]') == 1
+    manual_sensor = its.caps.manual_sensor(props)
 
     # Test: rollingShutterSkew, and frameDuration tags must all be present,
     # and rollingShutterSkew must be greater than zero and smaller than all
     # of the possible frame durations.
-    check('md.has_key("android.sensor.frameDuration")')
-    check('md["android.sensor.frameDuration"] is not None')
+    if manual_sensor:
+        check('md.has_key("android.sensor.frameDuration")')
+        check('md["android.sensor.frameDuration"] is not None')
     check('md.has_key("android.sensor.rollingShutterSkew")')
     check('md["android.sensor.rollingShutterSkew"] is not None')
-    check('md["android.sensor.frameDuration"] > '
-          'md["android.sensor.rollingShutterSkew"] > 0')
+    if manual_sensor:
+        check('md["android.sensor.frameDuration"] > '
+              'md["android.sensor.rollingShutterSkew"] > 0')
 
     # Test: timestampSource must be a valid value.
     check('props.has_key("android.sensor.info.timestampSource")')
diff --git a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
index 910cda2..73834cb 100644
--- a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
@@ -192,8 +192,8 @@
 
             # Verify reprocessing HQ(2) is similar to regular HQ(2) relative to
             # OFF(0)
-            assert(numpy.isclose(sharpness_reprocess[reprocess_format][2] /
-                                    sharpness_reprocess[reprocess_format][0],
+            assert(numpy.isclose(sharpnesses_reprocess[reprocess_format][2] /
+                                    sharpnesses_reprocess[reprocess_format][0],
                                  sharpness_regular[2] / sharpness_regular[0],
                                  THRESHOLD_RELATIVE_SHARPNESS_DIFF))
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 3037376..27f8c28 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -1484,13 +1484,32 @@
 
                 StringBuilder logMsg = new StringBuilder();
                 logMsg.append(String.format(
-                        "Capt result: AE=%d, AF=%d, AWB=%d, sens=%d, exp=%.1fms, dur=%.1fms, ",
+                        "Capt result: AE=%d, AF=%d, AWB=%d, ",
                         result.get(CaptureResult.CONTROL_AE_STATE),
                         result.get(CaptureResult.CONTROL_AF_STATE),
-                        result.get(CaptureResult.CONTROL_AWB_STATE),
-                        result.get(CaptureResult.SENSOR_SENSITIVITY),
-                        result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue() / 1000000.0f,
-                        result.get(CaptureResult.SENSOR_FRAME_DURATION).intValue() / 1000000.0f));
+                        result.get(CaptureResult.CONTROL_AWB_STATE)));
+                int[] capabilities = mCameraCharacteristics.get(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+                if (capabilities == null) {
+                    throw new ItsException("Failed to get capabilities");
+                }
+                boolean readSensorSettings = false;
+                for (int capability : capabilities) {
+                    if (capability ==
+                            CameraCharacteristics.
+                                    REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS) {
+                        readSensorSettings = true;
+                        break;
+                    }
+                }
+                if (readSensorSettings) {
+                    logMsg.append(String.format(
+                            "sens=%d, exp=%.1fms, dur=%.1fms, ",
+                            result.get(CaptureResult.SENSOR_SENSITIVITY),
+                            result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue() / 1000000.0f,
+                            result.get(CaptureResult.SENSOR_FRAME_DURATION).intValue() /
+                                        1000000.0f));
+                }
                 if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
                     logMsg.append(String.format(
                             "gains=[%.1f, %.1f, %.1f, %.1f], ",
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
index 34f2d85..8ccc931 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -306,9 +306,6 @@
             {YUV , MAXIMUM, PRIV, PREVIEW, YUV , RECORD},
             {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , MAXIMUM},
             {PRIV, MAXIMUM, YUV , PREVIEW, YUV , MAXIMUM},
-            {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , RECORD , JPEG, RECORD},
-            {YUV , MAXIMUM, PRIV, PREVIEW, YUV , RECORD , JPEG, RECORD},
-            {PRIV, MAXIMUM, YUV , PREVIEW, PRIV, PREVIEW, YUV , MAXIMUM},
             {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
             {YUV , MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
         };
@@ -1218,7 +1215,7 @@
                 MaxStreamSizes.reprocessConfigToString(reprocessConfig)));
 
         final int TIMEOUT_FOR_RESULT_MS = 3000;
-        final int NUM_REPROCESS_CAPTURES = 3;
+        final int NUM_REPROCESS_CAPTURES_PER_CONFIG = 3;
 
         List<SurfaceTexture> privTargets = new ArrayList<>();
         List<ImageReader> jpegTargets = new ArrayList<>();
@@ -1243,64 +1240,75 @@
         }
 
         try {
-            // reprocessConfig[0:1] is input
-            InputConfiguration inputConfig = getInputConfig(
-                    Arrays.copyOfRange(reprocessConfig, 0, 2), maxSizes);
-
-
-            inputReader = ImageReader.newInstance(inputConfig.getWidth(), inputConfig.getHeight(),
-                    inputConfig.getFormat(), NUM_REPROCESS_CAPTURES);
-            inputReader.setOnImageAvailableListener(inputReaderListener, mHandler);
-            outputSurfaces.add(inputReader.getSurface());
-
             // reprocessConfig[2..] are additional outputs
             setupConfigurationTargets(
                     Arrays.copyOfRange(reprocessConfig, 2, reprocessConfig.length),
                     maxSizes, privTargets, jpegTargets, yuvTargets, rawTargets, outputSurfaces,
-                    NUM_REPROCESS_CAPTURES);
+                    NUM_REPROCESS_CAPTURES_PER_CONFIG);
+
+            // reprocessConfig[0:1] is input
+            InputConfiguration inputConfig = getInputConfig(
+                    Arrays.copyOfRange(reprocessConfig, 0, 2), maxSizes);
+
+            // For each config, YUV and JPEG outputs will be tested. (For YUV reprocessing,
+            // the YUV ImageReader for input is also used for output.)
+            final int totalNumReprocessCaptures =  NUM_REPROCESS_CAPTURES_PER_CONFIG * (
+                    (inputConfig.getFormat() == ImageFormat.YUV_420_888 ? 1 : 0) +
+                    jpegTargets.size() + yuvTargets.size());
+
+            // It needs 1 input buffer for each reprocess capture + the number of buffers
+            // that will be used as outputs.
+            inputReader = ImageReader.newInstance(inputConfig.getWidth(), inputConfig.getHeight(),
+                    inputConfig.getFormat(),
+                    totalNumReprocessCaptures + NUM_REPROCESS_CAPTURES_PER_CONFIG);
+            inputReader.setOnImageAvailableListener(inputReaderListener, mHandler);
+            outputSurfaces.add(inputReader.getSurface());
 
             // Verify we can create a reprocessable session with the input and all outputs.
             BlockingSessionCallback sessionListener = new BlockingSessionCallback();
             CameraCaptureSession session = configureReprocessableCameraSession(mCamera,
                     inputConfig, outputSurfaces, sessionListener, mHandler);
             inputWriter = ImageWriter.newInstance(session.getInputSurface(),
-                    NUM_REPROCESS_CAPTURES);
+                    totalNumReprocessCaptures);
 
             // Prepare a request for reprocess input
             CaptureRequest.Builder builder = mCamera.createCaptureRequest(
                     CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
             builder.addTarget(inputReader.getSurface());
 
-            for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
+            for (int i = 0; i < totalNumReprocessCaptures; i++) {
                 session.capture(builder.build(), inputCaptureListener, mHandler);
             }
 
             List<CaptureRequest> reprocessRequests = new ArrayList<>();
-            int numReprocessOutputs = 0;
+            List<Surface> reprocessOutputs = new ArrayList<>();
+            if (inputConfig.getFormat() == ImageFormat.YUV_420_888) {
+                reprocessOutputs.add(inputReader.getSurface());
+            }
 
-            for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
-                TotalCaptureResult result = inputCaptureListener.getTotalCaptureResult(
-                        TIMEOUT_FOR_RESULT_MS);
-                builder =  mCamera.createReprocessCaptureRequest(result);
-                inputWriter.queueInputImage(inputReaderListener.getImage(TIMEOUT_FOR_RESULT_MS));
+            for (ImageReader reader : jpegTargets) {
+                reprocessOutputs.add(reader.getSurface());
+            }
 
-                // Test mandatory YUV and JPEG reprocess outputs.
-                for (ImageReader reader : jpegTargets) {
-                    builder.addTarget(reader.getSurface());
-                    numReprocessOutputs++;
+            for (ImageReader reader : yuvTargets) {
+                reprocessOutputs.add(reader.getSurface());
+            }
+
+            for (int i = 0; i < NUM_REPROCESS_CAPTURES_PER_CONFIG; i++) {
+                for (Surface output : reprocessOutputs) {
+                    TotalCaptureResult result = inputCaptureListener.getTotalCaptureResult(
+                            TIMEOUT_FOR_RESULT_MS);
+                    builder =  mCamera.createReprocessCaptureRequest(result);
+                    inputWriter.queueInputImage(
+                            inputReaderListener.getImage(TIMEOUT_FOR_RESULT_MS));
+                    builder.addTarget(output);
+                    reprocessRequests.add(builder.build());
                 }
-
-                for (ImageReader reader : yuvTargets) {
-                    builder.addTarget(reader.getSurface());
-                    numReprocessOutputs++;
-                }
-
-                reprocessRequests.add(builder.build());
             }
 
             session.captureBurst(reprocessRequests, reprocessOutputCaptureListener, mHandler);
 
-            for (int i = 0; i < numReprocessOutputs; i++) {
+            for (int i = 0; i < reprocessOutputs.size() * NUM_REPROCESS_CAPTURES_PER_CONFIG; i++) {
                 TotalCaptureResult result = reprocessOutputCaptureListener.getTotalCaptureResult(
                         TIMEOUT_FOR_RESULT_MS);
             }