cameraserver: Reduced Quad Bayer support.

Allow devices which don't have the ULTRA_HIGH_RESOLUTION_SENSOR
capability to get the same framework behaviour as devices which:
     1) SENSOR_PIXEL_MODE is advertised in ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS
     2) The following keys are present in CameraCharacteristics for basic functionality
            a) ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
            b) ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION
            c) ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION
            d) ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
            e) ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
            f) ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION

Bug: 261232769

Test: Manual

Change-Id: Ib2261a63b9d1cf7d960ab158fa66dc65160c3344
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 18b28b8..f0e3755 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -191,11 +191,11 @@
     // Cache physical camera ids corresponding to this device and also the high
     // resolution sensors in this device + physical camera ids
     mProviderManager->isLogicalCamera(mCameraIdStr.string(), &mPhysicalCameraIds);
-    if (isUltraHighResolutionSensor(mCameraIdStr)) {
+    if (supportsUltraHighResolutionCapture(mCameraIdStr)) {
         mHighResolutionSensors.insert(mCameraIdStr.string());
     }
     for (auto &physicalId : mPhysicalCameraIds) {
-        if (isUltraHighResolutionSensor(String8(physicalId.c_str()))) {
+        if (supportsUltraHighResolutionCapture(String8(physicalId.c_str()))) {
             mHighResolutionSensors.insert(physicalId.c_str());
         }
     }
@@ -2247,9 +2247,9 @@
     return mDevice->infoPhysical(cameraId);
 }
 
-bool CameraDeviceClient::isUltraHighResolutionSensor(const String8 &cameraId) {
+bool CameraDeviceClient::supportsUltraHighResolutionCapture(const String8 &cameraId) {
     const CameraMetadata &deviceInfo = getStaticInfo(cameraId);
-    return SessionConfigurationUtils::isUltraHighResolutionSensor(deviceInfo);
+    return SessionConfigurationUtils::supportsUltraHighResolutionCapture(deviceInfo);
 }
 
 bool CameraDeviceClient::isSensorPixelModeConsistent(
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 36c627a..c6688a5 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -242,7 +242,7 @@
     // Calculate the ANativeWindow transform from android.sensor.orientation
     status_t              getRotationTransformLocked(int mirrorMode, /*out*/int32_t* transform);
 
-    bool isUltraHighResolutionSensor(const String8 &cameraId);
+    bool supportsUltraHighResolutionCapture(const String8 &cameraId);
 
     bool isSensorPixelModeConsistent(const std::list<int> &streamIdList,
             const CameraMetadata &settings);
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index a3547dd..737c2b5 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -98,7 +98,7 @@
         }
 
         getSupportedDepthSizes(staticInfo, /*maxResolution*/false, &mSupportedDepthSizes);
-        if (SessionConfigurationUtils::isUltraHighResolutionSensor(staticInfo)) {
+        if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(staticInfo)) {
             getSupportedDepthSizes(staticInfo, true, &mSupportedDepthSizesMaximumResolution);
         }
     }
@@ -901,7 +901,7 @@
         return BAD_VALUE;
     }
 
-    if (SessionConfigurationUtils::isUltraHighResolutionSensor(ch)) {
+    if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(ch)) {
         getSupportedDepthSizes(ch, /*maxResolution*/true, &depthSizesMaximumResolution);
         if (depthSizesMaximumResolution.empty()) {
             ALOGE("%s: No depth stream configurations for maximum resolution present",
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 30ebd91..99c6a27 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -506,8 +506,8 @@
         ALOGE("%s: Unable to derive Jpeg/R tags based on camera and media capabilities: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
     }
-
-    if (camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
+    using camera3::SessionConfigurationUtils::supportsUltraHighResolutionCapture;
+    if (supportsUltraHighResolutionCapture(mCameraCharacteristics)) {
         status_t status = addDynamicDepthTags(/*maxResolution*/true);
         if (OK != status) {
             ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 0e83191..efdf238 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -625,7 +625,7 @@
                 __FUNCTION__, strerror(-res), res);
     }
 
-    if (SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
+    if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(mCameraCharacteristics)) {
         status_t status = addDynamicDepthTags(/*maxResolution*/true);
         if (OK != status) {
             ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 9faea20..7130025 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -218,7 +218,7 @@
     mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
             mSupportNativeZoomRatio, usePrecorrectArray);
 
-    if (SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo)) {
+    if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(mDeviceInfo)) {
         mUHRCropAndMeteringRegionMappers[mId.c_str()] =
                 UHRCropAndMeteringRegionMapper(mDeviceInfo, usePrecorrectArray);
     }
@@ -406,7 +406,7 @@
     // Get max jpeg size (area-wise) for default sensor pixel mode
     camera3::Size maxDefaultJpegResolution =
             SessionConfigurationUtils::getMaxJpegResolution(info,
-                    /*isUltraHighResolutionSensor*/false);
+                    /*supportsUltraHighResolutionCapture*/false);
     // Get max jpeg size (area-wise) for max resolution sensor pixel mode / 0 if
     // not ultra high res sensor
     camera3::Size uhrMaxJpegResolution =
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.cpp b/services/camera/libcameraservice/device3/DistortionMapper.cpp
index 15807bf..f0764b4 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.cpp
+++ b/services/camera/libcameraservice/device3/DistortionMapper.cpp
@@ -67,7 +67,7 @@
         return res;
     }
 
-    bool mMaxResolution = SessionConfigurationUtils::isUltraHighResolutionSensor(deviceInfo);
+    bool mMaxResolution = SessionConfigurationUtils::supportsUltraHighResolutionCapture(deviceInfo);
     if (mMaxResolution) {
         res = setupStaticInfoLocked(deviceInfo, /*maxResolution*/true);
     }
diff --git a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
index c558d91..ce7097a 100644
--- a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
+++ b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
@@ -91,6 +91,8 @@
         if (meteringRegionsSetEntry.count == 1 &&
                 meteringRegionsSetEntry.data.u8[0] == entry.second.second) {
             // metering region set by client, doesn't need to be fixed.
+            ALOGV("%s: Metering region %u set by client, they don't need to be fixed",
+                    __FUNCTION__, entry.first);
             continue;
         }
         camera_metadata_entry meteringRegionEntry = request->find(entry.first);
@@ -121,6 +123,7 @@
     if (cropRegionSetEntry.count == 1 &&
         cropRegionSetEntry.data.u8[0] == ANDROID_SCALER_CROP_REGION_SET_TRUE) {
         // crop regions set by client, doesn't need to be fixed.
+        ALOGV("%s: crop region set by client, doesn't need to be fixed", __FUNCTION__);
         return;
     }
     camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 515259e..aaa1b70 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -153,9 +153,9 @@
         return;
     }
 
-    bool isUltraHighResolutionSensor =
-            camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(*deviceInfo);
-    if (isUltraHighResolutionSensor) {
+    bool supportsUltraHighResolutionCapture =
+            camera3::SessionConfigurationUtils::supportsUltraHighResolutionCapture(*deviceInfo);
+    if (supportsUltraHighResolutionCapture) {
         if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
                 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
                 &arrayMaximumResolutionW, &arrayMaximumResolutionH)) {
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 30f6d18..2211583 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -238,7 +238,7 @@
                     &mPhysicalDeviceInfoMap[physicalId],
                     mSupportNativeZoomRatio, usePrecorrectArray);
 
-            if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+            if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(
                     mPhysicalDeviceInfoMap[physicalId])) {
                 mUHRCropAndMeteringRegionMappers[physicalId] =
                         UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 382b287..8f9abfa 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -203,7 +203,7 @@
                     &mPhysicalDeviceInfoMap[physicalId],
                     mSupportNativeZoomRatio, usePrecorrectArray);
 
-            if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+            if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(
                     mPhysicalDeviceInfoMap[physicalId])) {
                 mUHRCropAndMeteringRegionMappers[physicalId] =
                         UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index f786b79..48b27be 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -196,6 +196,8 @@
 
     if (bestWidth == -1) {
         // Return false if no configurations for this format were listed
+        ALOGE("%s: No configurations for format %d width %d, height %d, maxResolution ? %s",
+                __FUNCTION__, format, width, height, maxResolution ? "true" : "false");
         return false;
     }
 
@@ -937,7 +939,7 @@
 
     const std::unordered_set<int32_t> &sensorPixelModesUsedSet =
             convertToSet(sensorPixelModesUsed);
-    if (!isUltraHighResolutionSensor(staticInfo)) {
+    if (!supportsUltraHighResolutionCapture(staticInfo)) {
         if (sensorPixelModesUsedSet.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
                 sensorPixelModesUsedSet.end()) {
             // invalid value for non ultra high res sensors
@@ -961,12 +963,14 @@
     // Case 1: The client has not changed the sensor mode defaults. In this case, we check if the
     // size + format of the OutputConfiguration is found exclusively in 1.
     // If yes, add that sensorPixelMode to overriddenSensorPixelModes.
-    // If no, add 'DEFAULT' to sensorPixelMode. This maintains backwards
-    // compatibility.
+    // If no, add 'DEFAULT' and MAXIMUM_RESOLUTION to overriddenSensorPixelModes.
+    // This maintains backwards compatibility and also tells the framework the stream
+    // might be used in either sensor pixel mode.
     if (sensorPixelModesUsedSet.size() == 0) {
-        // Ambiguous case, default to only 'DEFAULT' mode.
+        // Ambiguous case, override to include both cases.
         if (isInDefaultStreamConfigurationMap && isInMaximumResolutionStreamConfigurationMap) {
             overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
+            overriddenSensorPixelModesUsed->insert(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
             return OK;
         }
         // We don't allow flexible consumer for max resolution mode.
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.cpp
index 28a22e1..7d344f8 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.cpp
@@ -73,7 +73,62 @@
     return -1;
 }
 
-bool isUltraHighResolutionSensor(const CameraMetadata &deviceInfo) {
+static bool isKeyPresentWithCount(const CameraMetadata &deviceInfo, uint32_t tag, uint32_t count) {
+    auto countFound = deviceInfo.find(tag).count;
+    return (countFound != 0) && (countFound % count == 0);
+}
+
+static bool supportsKeysForBasicUltraHighResolutionCapture(const CameraMetadata &deviceInfo) {
+    // Check whether the following conditions are satisfied for reduced ultra high
+    // resolution support :
+    // 1) SENSOR_PIXEL_MODE is advertised in ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS
+    // 2) The following keys are present in CameraCharacteristics for basic functionality
+    //        a) ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+    //        b) ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION
+    //        c) ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION
+    //        d) ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
+    //        e) ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
+    //        f) ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION
+    camera_metadata_ro_entry_t entryChar;
+    entryChar = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
+    bool supportsSensorPixelMode = false;
+    for (size_t i = 0; i < entryChar.count; i++) {
+        int32_t key = entryChar.data.i32[i];
+        if (key == ANDROID_SENSOR_PIXEL_MODE) {
+            supportsSensorPixelMode = true;
+            break;
+        }
+    }
+    if (!supportsSensorPixelMode) {
+        return false;
+    }
+
+    // Basic sensor array size information tags are present
+    if (!isKeyPresentWithCount(deviceInfo, ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+            /*count*/2) ||
+            !isKeyPresentWithCount(deviceInfo,
+                    ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+                    /*count*/4) ||
+            !isKeyPresentWithCount(deviceInfo,
+                    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION, /*count*/4) ||
+            !isKeyPresentWithCount(deviceInfo, ANDROID_SENSOR_INFO_BINNING_FACTOR, /*count*/2)) {
+        return false;
+    }
+
+    // Basic stream configuration tags are present
+    if (!isKeyPresentWithCount(deviceInfo,
+            ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION, /*count*/4) ||
+            !isKeyPresentWithCount(deviceInfo,
+                    ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION, /*count*/4) ||
+            !isKeyPresentWithCount(deviceInfo,
+                    ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION, /*count*/ 4)) {
+        return false;
+    }
+
+    return true;
+}
+
+bool supportsUltraHighResolutionCapture(const CameraMetadata &deviceInfo) {
     camera_metadata_ro_entry_t entryCap;
     entryCap = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
     // Go through the capabilities and check if it has
@@ -84,7 +139,10 @@
             return true;
         }
     }
-    return false;
+
+    // If not, then check that the keys which guarantee basic supports for
+    // ultra high resolution capture are supported.
+    return supportsKeysForBasicUltraHighResolutionCapture(deviceInfo);
 }
 
 bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.h b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.h
index 45b1e91..dac1824 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHost.h
@@ -22,7 +22,7 @@
 namespace camera3 {
 namespace SessionConfigurationUtils {
 
-bool isUltraHighResolutionSensor(const CameraMetadata &deviceInfo);
+bool supportsUltraHighResolutionCapture(const CameraMetadata &deviceInfo);
 
 int32_t getAppropriateModeTag(int32_t defaultTag, bool maxResolution = false);
 
@@ -33,4 +33,4 @@
 } // camera3
 } // android
 
-#endif
\ No newline at end of file
+#endif