Camera: Implement legacy device stream combination query

Use the legacy stream configuration logic to check for
support of a given session configuration.

Bug: 111593096
Test:
runtest -x
cts/tests/camera/src/android/hardware/camera2/cts/MultiViewTest.java
runtest -x
cts/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java -m
testMandatoryOutputCombinations
runtest -x
cts/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java -m
testBadSurfaceDimensions
runtest -x
cts/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java -m
testMandatoryReprocessConfigurations
runtest -x
cts/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
-m testDeferredSurfaces

Change-Id: I921f94be8212a55fa90150cb35ea06e488dc0b29
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 8971f8d..3e130c5 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -484,8 +484,38 @@
 
     @Override
     public boolean isSessionConfigurationSupported(SessionConfiguration sessionConfig) {
-        // TODO: Add support for this in legacy mode
-        throw new UnsupportedOperationException("Session configuration query not supported!");
+        if (sessionConfig.getSessionType() != SessionConfiguration.SESSION_REGULAR) {
+            Log.e(TAG, "Session type: " + sessionConfig.getSessionType() + " is different from " +
+                    " regular. Legacy devices support only regular session types!");
+            return false;
+        }
+
+        if (sessionConfig.getInputConfiguration() != null) {
+            Log.e(TAG, "Input configuration present, legacy devices do not support this feature!");
+            return false;
+        }
+
+        List<OutputConfiguration> outputConfigs = sessionConfig.getOutputConfigurations();
+        if (outputConfigs.isEmpty()) {
+            Log.e(TAG, "Empty output configuration list!");
+            return false;
+        }
+
+        SparseArray<Surface> surfaces = new SparseArray<Surface>(outputConfigs.size());
+        int idx = 0;
+        for (OutputConfiguration outputConfig : outputConfigs) {
+            List<Surface> surfaceList = outputConfig.getSurfaces();
+            if (surfaceList.isEmpty() || (surfaceList.size() > 1)) {
+                Log.e(TAG, "Legacy devices do not support deferred or shared surfaces!");
+                return false;
+            }
+
+            surfaces.put(idx++, outputConfig.getSurface());
+        }
+
+        int ret = mLegacyDevice.configureOutputs(surfaces, /*validateSurfacesOnly*/true);
+
+        return ret == LegacyExceptionUtils.NO_ERROR;
     }
 
     @Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 71a361b..aff09f2 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -346,6 +346,25 @@
      *          on success.
      */
     public int configureOutputs(SparseArray<Surface> outputs) {
+        return configureOutputs(outputs, /*validateSurfacesOnly*/false);
+    }
+
+    /**
+     * Configure the device with a set of output surfaces.
+     *
+     * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p>
+     *
+     * <p>Every surface in {@code outputs} must be non-{@code null}.</p>
+     *
+     * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this
+     *          list; it must not be modified by the caller once it's passed in.
+     * @param validateSurfacesOnly If set it will only check whether the outputs are supported
+     *                             and avoid any device configuration.
+     * @return an error code for this binder operation, or {@link NO_ERROR}
+     *          on success.
+     * @hide
+     */
+    public int configureOutputs(SparseArray<Surface> outputs, boolean validateSurfacesOnly) {
         List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
         if (outputs != null) {
             int count = outputs.size();
@@ -397,7 +416,9 @@
                         sizedSurfaces.add(new Pair<>(output, s));
                     }
                     // Lock down the size before configuration
-                    setSurfaceDimens(output, s.getWidth(), s.getHeight());
+                    if (!validateSurfacesOnly) {
+                        setSurfaceDimens(output, s.getWidth(), s.getHeight());
+                    }
                 } catch (BufferQueueAbandonedException e) {
                     Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e);
                     return BAD_VALUE;
@@ -406,6 +427,10 @@
             }
         }
 
+        if (validateSurfacesOnly) {
+            return LegacyExceptionUtils.NO_ERROR;
+        }
+
         boolean success = false;
         if (mDeviceState.setConfiguring()) {
             mRequestThreadManager.configure(sizedSurfaces);