Camera: waive some QCIF size combinations

Test: locally modified Pixel 3 camera HAL
Bug: 122524858
Bug: 120158047
Change-Id: I474c9a8c191a22eeeb8876381c4841a59426831a
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index 8852778..ef174fa 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -361,7 +361,8 @@
 
                 Size maxJpegSize = CameraTestUtils.getMaxSize(jpegSizes);
                 Size maxPreviewSize = mOrderedPreviewSizes.get(0);
-
+                Size QCIF = new Size(176, 144);
+                Size FULL_HD = new Size(1920, 1080);
                 for (int format : supportedYUVFormats) {
                     Size[] targetCaptureSizes =
                             mStaticInfo.getAvailableSizesForFormatChecked(format,
@@ -409,6 +410,14 @@
                                             + "max preview size (" + maxPreviewSize
                                             + ") is not supported");
                                     continue;
+                                } else if (captureSz.equals(QCIF) &&
+                                        ((maxJpegSize.getWidth() > FULL_HD.getWidth()) ||
+                                         (maxJpegSize.getHeight() > FULL_HD.getHeight()))) {
+                                    Log.v(TAG, "Skip testing {yuv:" + captureSz
+                                            + " ,jpeg:" + maxJpegSize + "} for camera "
+                                            + mCamera.getId() +
+                                            " because QCIF + >Full_HD size is not supported");
+                                    continue;
                                 } else {
                                     fail("Camera " + mCamera.getId() +
                                             ":session configuration failed for {jpeg: " +
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 651b8b6..7617043 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1151,6 +1151,8 @@
             }
 
             CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+            Size QCIF = new Size(176, 144);
+            Size FULL_HD = new Size(1920, 1080);
             Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
             Size maxPreviewSize = mOrderedPreviewSizes.get(0);
 
@@ -1227,8 +1229,6 @@
                 }
             }
 
-            Log.i(TAG, "Testing video snapshot size " + videoSnapshotSz +
-                    " for video size " + videoSz);
             if (videoSnapshotSz.getWidth() * videoSnapshotSz.getHeight() > FRAME_SIZE_15M)
                 kFrameDrop_Tolerence = (int)(FRAMEDROP_TOLERANCE * FRAME_DROP_TOLERENCE_FACTOR);
 
@@ -1253,6 +1253,26 @@
                 }
             }
 
+            if (videoSz.equals(QCIF) &&
+                    ((videoSnapshotSz.getWidth() > FULL_HD.getWidth()) ||
+                     (videoSnapshotSz.getHeight() > FULL_HD.getHeight()))) {
+                List<Surface> outputs = new ArrayList<Surface>();
+                outputs.add(mPreviewSurface);
+                outputs.add(mRecordingSurface);
+                outputs.add(mReaderSurface);
+                boolean isSupported = isStreamConfigurationSupported(
+                        mCamera, outputs, mSessionListener, mHandler);
+                if (!isSupported) {
+                    videoSnapshotSz = defaultvideoSnapshotSz;
+                    createImageReader(
+                            videoSnapshotSz, ImageFormat.JPEG,
+                            MAX_VIDEO_SNAPSHOT_IMAGES, /*listener*/null);
+                }
+            }
+
+            Log.i(TAG, "Testing video snapshot size " + videoSnapshotSz +
+                    " for video size " + videoSz);
+
             if (VERBOSE) {
                 Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
             }
diff --git a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index f30ca92..57b470e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -511,6 +511,9 @@
     private void testReprocessingAllCombinations(String cameraId, Size previewSize,
             CaptureTestCase captureTestCase) throws Exception {
 
+        Size QCIF = new Size(176, 144);
+        Size VGA = new Size(640, 480);
+        Size FULL_HD = new Size(1920, 1080);
         int[] supportedInputFormats =
                 mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
         for (int inputFormat : supportedInputFormats) {
@@ -528,6 +531,24 @@
                             StaticMetadata.StreamDirection.Output);
 
                     for (Size reprocessOutputSize : supportedReprocessOutputSizes) {
+                        // Handle QCIF exceptions
+                        if (reprocessOutputSize.equals(QCIF) &&
+                                ((inputSize.getWidth() > FULL_HD.getWidth()) ||
+                                 (inputSize.getHeight() > FULL_HD.getHeight()))) {
+                            continue;
+                        }
+                        if (inputSize.equals(QCIF) &&
+                                ((reprocessOutputSize.getWidth() > FULL_HD.getWidth()) ||
+                                 (reprocessOutputSize.getHeight() > FULL_HD.getHeight()))) {
+                            continue;
+                        }
+                        if ((previewSize != null) &&
+                                ((previewSize.getWidth() > FULL_HD.getWidth()) || (
+                                  previewSize.getHeight() > FULL_HD.getHeight())) &&
+                                (inputSize.equals(QCIF) || reprocessOutputSize.equals(QCIF))) {
+                            previewSize = VGA;
+                        }
+
                         switch (captureTestCase) {
                             case SINGLE_SHOT:
                                 testReprocess(cameraId, inputSize, inputFormat,
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index e77ad79..f327b30 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -894,6 +894,8 @@
         SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
         SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
 
+        Size QCIF = new Size(176, 144);
+        Size FULL_HD = new Size(1920, 1080);
         for (Size stillSz : mOrderedStillSizes)
             for (Size previewSz : mOrderedPreviewSizes) {
                 if (VERBOSE) {
@@ -901,6 +903,20 @@
                             + " with preview size " + previewSz.toString() + " for camera "
                             + mCamera.getId());
                 }
+
+                // Skip testing QCIF + >FullHD combinations
+                if (stillSz.equals(QCIF) &&
+                        ((previewSz.getWidth() > FULL_HD.getWidth()) ||
+                         (previewSz.getHeight() > FULL_HD.getHeight()))) {
+                    continue;
+                }
+
+                if (previewSz.equals(QCIF) &&
+                        ((stillSz.getWidth() > FULL_HD.getWidth()) ||
+                         (stillSz.getHeight() > FULL_HD.getHeight()))) {
+                    continue;
+                }
+
                 CaptureRequest.Builder previewRequest =
                         mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                 CaptureRequest.Builder stillRequest =
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index 81b42ef..c58d1df 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -470,10 +470,20 @@
         // Test all preview sizes.
         initializeMessageLooper(cameraId);
         Parameters parameters = mCamera.getParameters();
+
+        Size QCIF = mCamera.new Size(176, 144);
+        Size VGA = mCamera.new Size(640, 480);
+        Size defaultPicSize = parameters.getPictureSize();
+
         for (Size size: parameters.getSupportedPreviewSizes()) {
             mPreviewCallbackResult = PREVIEW_CALLBACK_NOT_RECEIVED;
             mCamera.setPreviewCallback(mPreviewCallback);
             parameters.setPreviewSize(size.width, size.height);
+            if (size.equals(QCIF)) {
+                parameters.setPictureSize(VGA.width, VGA.height);
+            } else {
+                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.height);
+            }
             mCamera.setParameters(parameters);
             assertEquals(size, mCamera.getParameters().getPreviewSize());
             checkPreviewCallback();
@@ -1413,8 +1423,17 @@
         mCamera.setPreviewDisplay(surfaceHolder);
         Parameters parameters = mCamera.getParameters();
         PreviewCallbackWithBuffer callback = new PreviewCallbackWithBuffer();
+        Size QCIF = mCamera.new Size(176, 144);
+        Size VGA = mCamera.new Size(640, 480);
+        Size defaultPicSize = parameters.getPictureSize();
+
         // Test all preview sizes.
         for (Size size: parameters.getSupportedPreviewSizes()) {
+            if (size.equals(QCIF)) {
+                parameters.setPictureSize(VGA.width, VGA.height);
+            } else {
+                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.height);
+            }
             parameters.setPreviewSize(size.width, size.height);
             mCamera.setParameters(parameters);
             assertEquals(size, mCamera.getParameters().getPreviewSize());
@@ -1503,11 +1522,20 @@
             return;
         }
 
+        Size QCIF = mCamera.new Size(176, 144);
+        Size VGA = mCamera.new Size(640, 480);
+        Size defaultPicSize = parameters.getPictureSize();
+
         // Test the zoom parameters.
         assertEquals(0, parameters.getZoom());  // default zoom should be 0.
         for (Size size: parameters.getSupportedPreviewSizes()) {
             parameters = mCamera.getParameters();
             parameters.setPreviewSize(size.width, size.height);
+            if (size.equals(QCIF)) {
+                parameters.setPictureSize(VGA.width, VGA.height);
+            } else {
+                parameters.setPictureSize(defaultPicSize.width, defaultPicSize.height);
+            }
             mCamera.setParameters(parameters);
             parameters = mCamera.getParameters();
             int maxZoom = parameters.getMaxZoom();
@@ -1932,6 +1960,22 @@
         }
     }
 
+    // API exception on QCIF size. QCIF size along with anything larger than
+    // 1920x1080 on either width/height is not guaranteed to be supported.
+    private boolean isWaivedCombination(Size previewSize, Size pictureSize) {
+        Size QCIF = mCamera.new Size(176, 144);
+        Size FULL_HD = mCamera.new Size(1920, 1080);
+        if (previewSize.equals(QCIF) && (pictureSize.width > FULL_HD.width ||
+                pictureSize.height > FULL_HD.height)) {
+            return true;
+        }
+        if (pictureSize.equals(QCIF) && (previewSize.width > FULL_HD.width ||
+                previewSize.height > FULL_HD.height)) {
+            return true;
+        }
+        return false;
+    }
+
     private void testPreviewPictureSizesCombinationByCamera(int cameraId) throws Exception {
         initializeMessageLooper(cameraId);
         Parameters parameters = mCamera.getParameters();
@@ -1949,12 +1993,33 @@
                 callback.expectedPreviewSize = previewSize;
                 parameters.setPreviewSize(previewSize.width, previewSize.height);
                 parameters.setPictureSize(pictureSize.width, pictureSize.height);
-                mCamera.setParameters(parameters);
+                try {
+                    mCamera.setParameters(parameters);
+                } catch (RuntimeException e) {
+                    if (isWaivedCombination(previewSize, pictureSize)) {
+                        Log.i(TAG, String.format("Preview %dx%d and still %dx%d combination is" +
+                                "waived", previewSize.width, previewSize.height,
+                                pictureSize.width, pictureSize.height));
+                        continue;
+                    }
+                    throw e;
+                }
+
                 assertEquals(previewSize, mCamera.getParameters().getPreviewSize());
                 assertEquals(pictureSize, mCamera.getParameters().getPictureSize());
 
                 // Check if the preview size is the same as requested.
-                mCamera.startPreview();
+                try {
+                    mCamera.startPreview();
+                } catch (RuntimeException e) {
+                    if (isWaivedCombination(previewSize, pictureSize)) {
+                        Log.i(TAG, String.format("Preview %dx%d and still %dx%d combination is" +
+                                "waived", previewSize.width, previewSize.height,
+                                pictureSize.width, pictureSize.height));
+                        continue;
+                    }
+                    throw e;
+                }
                 waitForPreviewDone();
                 assertEquals(PREVIEW_CALLBACK_RECEIVED, mPreviewCallbackResult);