Merge "C2 VTS: Use string::compare instead of string::find to match mime" into sc-dev
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 7272a74..d21908f 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -50,6 +50,8 @@
 static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000;
 // Default frame rate.
 static constexpr int32_t kDefaultFrameRate = 30;
+// Default codec complexity
+static constexpr int32_t kDefaultCodecComplexity = 1;
 
 template <typename T>
 void VideoTrackTranscoder::BlockingQueue<T>::push(T const& value, bool front) {
@@ -247,6 +249,7 @@
 
     SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_PRIORITY, encoderFormat, kDefaultCodecPriority);
     SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_FRAME_RATE, encoderFormat, kDefaultFrameRate);
+    SetDefaultFormatValueInt32(AMEDIAFORMAT_KEY_COMPLEXITY, encoderFormat, kDefaultCodecComplexity);
     AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
 
     // Always encode without rotation. The rotation degree will be transferred directly to
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index c28c24b..26562e0 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
         "device3/Camera3OutputStreamInterface.cpp",
         "device3/Camera3OutputUtils.cpp",
         "device3/Camera3DeviceInjectionMethods.cpp",
+        "device3/UHRCropAndMeteringRegionMapper.cpp",
         "gui/RingBufferConsumer.cpp",
         "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0101c58..fd645c7 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -171,6 +171,13 @@
             mZoomRatioMappers[physicalId] = ZoomRatioMapper(
                     &mPhysicalDeviceInfoMap[physicalId],
                     mSupportNativeZoomRatio, usePrecorrectArray);
+
+            if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+                    mPhysicalDeviceInfoMap[physicalId])) {
+                mUHRCropAndMeteringRegionMappers[physicalId] =
+                        UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
+                                usePrecorrectArray);
+            }
         }
     }
 
@@ -299,9 +306,25 @@
         sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
     }
 
+    camera_metadata_entry_t availableTestPatternModes = mDeviceInfo.find(
+            ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES);
+    for (size_t i = 0; i < availableTestPatternModes.count; i++) {
+        if (availableTestPatternModes.data.i32[i] ==
+                ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
+            mSupportCameraMute = true;
+            mSupportTestPatternSolidColor = true;
+            break;
+        } else if (availableTestPatternModes.data.i32[i] ==
+                ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+            mSupportCameraMute = true;
+            mSupportTestPatternSolidColor = false;
+        }
+    }
+
     /** Start up request queue thread */
     mRequestThread = new RequestThread(
-            this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
+            this, mStatusTracker, mInterface, sessionParamKeys,
+            mUseHalBufManager, mSupportCameraMute);
     res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
     if (res != OK) {
         SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -348,23 +371,13 @@
     mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
             mSupportNativeZoomRatio, usePrecorrectArray);
 
-    if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
-        mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
+    if (SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo)) {
+        mUHRCropAndMeteringRegionMappers[mId.c_str()] =
+                UHRCropAndMeteringRegionMapper(mDeviceInfo, usePrecorrectArray);
     }
 
-    camera_metadata_entry_t availableTestPatternModes = mDeviceInfo.find(
-            ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES);
-    for (size_t i = 0; i < availableTestPatternModes.count; i++) {
-        if (availableTestPatternModes.data.i32[i] ==
-                ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
-            mSupportCameraMute = true;
-            mSupportTestPatternSolidColor = true;
-            break;
-        } else if (availableTestPatternModes.data.i32[i] ==
-                ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
-            mSupportCameraMute = true;
-            mSupportTestPatternSolidColor = false;
-        }
+    if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
+        mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
     }
 
     mInjectionMethods = new Camera3DeviceInjectionMethods(this);
@@ -2450,9 +2463,9 @@
 
         auto testPatternDataEntry =
                 newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
-        if (testPatternDataEntry.count > 0) {
-            memcpy(newRequest->mOriginalTestPatternData, testPatternModeEntry.data.i32,
-                    sizeof(newRequest->mOriginalTestPatternData));
+        if (testPatternDataEntry.count >= 4) {
+            memcpy(newRequest->mOriginalTestPatternData, testPatternDataEntry.data.i32,
+                    sizeof(CaptureRequest::mOriginalTestPatternData));
         } else {
             newRequest->mOriginalTestPatternData[0] = 0;
             newRequest->mOriginalTestPatternData[1] = 0;
@@ -4143,7 +4156,8 @@
 Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
         sp<StatusTracker> statusTracker,
         sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys,
-        bool useHalBufManager) :
+        bool useHalBufManager,
+        bool supportCameraMute) :
         Thread(/*canCallJava*/false),
         mParent(parent),
         mStatusTracker(statusTracker),
@@ -4169,7 +4183,8 @@
         mRequestLatency(kRequestLatencyBinSize),
         mSessionParamKeys(sessionParamKeys),
         mLatestSessionParams(sessionParamKeys.size()),
-        mUseHalBufManager(useHalBufManager) {
+        mUseHalBufManager(useHalBufManager),
+        mSupportCameraMute(supportCameraMute){
     mStatusId = statusTracker->addComponent("RequestThread");
 }
 
@@ -4815,12 +4830,33 @@
             }
 
             {
-                // Correct metadata regions for distortion correction if enabled
                 sp<Camera3Device> parent = mParent.promote();
                 if (parent != nullptr) {
                     List<PhysicalCameraSettings>::iterator it;
                     for (it = captureRequest->mSettingsList.begin();
                             it != captureRequest->mSettingsList.end(); it++) {
+                        if (parent->mUHRCropAndMeteringRegionMappers.find(it->cameraId) ==
+                                parent->mUHRCropAndMeteringRegionMappers.end()) {
+                            continue;
+                        }
+
+                        if (!captureRequest->mUHRCropAndMeteringRegionsUpdated) {
+                            res = parent->mUHRCropAndMeteringRegionMappers[it->cameraId].
+                                    updateCaptureRequest(&(it->metadata));
+                            if (res != OK) {
+                                SET_ERR("RequestThread: Unable to correct capture requests "
+                                        "for scaler crop region and metering regions for request "
+                                        "%d: %s (%d)", halRequest->frame_number, strerror(-res),
+                                        res);
+                                return INVALID_OPERATION;
+                            }
+                            captureRequest->mUHRCropAndMeteringRegionsUpdated = true;
+                        }
+                    }
+
+                    // Correct metadata regions for distortion correction if enabled
+                    for (it = captureRequest->mSettingsList.begin();
+                            it != captureRequest->mSettingsList.end(); it++) {
                         if (parent->mDistortionMappers.find(it->cameraId) ==
                                 parent->mDistortionMappers.end()) {
                             continue;
@@ -5829,6 +5865,8 @@
         const sp<CaptureRequest> &request) {
     ATRACE_CALL();
 
+    if (!mSupportCameraMute) return false;
+
     Mutex::Autolock l(mTriggerMutex);
 
     bool changed = false;
@@ -5864,16 +5902,16 @@
     }
 
     auto testPatternColor = metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
-    if (testPatternColor.count > 0) {
+    if (testPatternColor.count >= 4) {
         for (size_t i = 0; i < 4; i++) {
-            if (testPatternColor.data.i32[i] != (int32_t)testPatternData[i]) {
+            if (testPatternColor.data.i32[i] != testPatternData[i]) {
                 testPatternColor.data.i32[i] = testPatternData[i];
                 changed = true;
             }
         }
     } else {
         metadata.update(ANDROID_SENSOR_TEST_PATTERN_DATA,
-                (int32_t*)testPatternData, 4);
+                testPatternData, 4);
         changed = true;
     }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 53a696f..39714f0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -50,6 +50,7 @@
 #include "device3/DistortionMapper.h"
 #include "device3/ZoomRatioMapper.h"
 #include "device3/RotateAndCropMapper.h"
+#include "device3/UHRCropAndMeteringRegionMapper.h"
 #include "device3/InFlightRequest.h"
 #include "device3/Camera3OutputInterface.h"
 #include "device3/Camera3OfflineSession.h"
@@ -589,6 +590,9 @@
         bool                                mRotationAndCropUpdated = false;
         // Whether this capture request's zoom ratio update has been done.
         bool                                mZoomRatioUpdated = false;
+        // Whether this max resolution capture request's  crop / metering region update has been
+        // done.
+        bool                                mUHRCropAndMeteringRegionsUpdated = false;
     };
     typedef List<sp<CaptureRequest> > RequestList;
 
@@ -809,7 +813,8 @@
                 sp<camera3::StatusTracker> statusTracker,
                 sp<HalInterface> interface,
                 const Vector<int32_t>& sessionParamKeys,
-                bool useHalBufManager);
+                bool useHalBufManager,
+                bool supportCameraMute);
         ~RequestThread();
 
         void     setNotificationListener(wp<NotificationListener> listener);
@@ -1082,6 +1087,7 @@
         std::map<int32_t, std::set<String8>> mGroupIdPhysicalCameraMap;
 
         const bool         mUseHalBufManager;
+        const bool         mSupportCameraMute;
     };
     sp<RequestThread> mRequestThread;
 
@@ -1224,6 +1230,12 @@
     std::unordered_map<std::string, camera3::ZoomRatioMapper> mZoomRatioMappers;
 
     /**
+     * UHR request crop / metering region mapper support
+     */
+    std::unordered_map<std::string, camera3::UHRCropAndMeteringRegionMapper>
+            mUHRCropAndMeteringRegionMappers;
+
+    /**
      * RotateAndCrop mapper support
      */
     std::unordered_map<std::string, camera3::RotateAndCropMapper> mRotateAndCropMappers;
diff --git a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
new file mode 100644
index 0000000..c558d91
--- /dev/null
+++ b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera3-UHRCropAndMeteringRegionMapper"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <cmath>
+
+#include "device3/UHRCropAndMeteringRegionMapper.h"
+#include "utils/SessionConfigurationUtils.h"
+
+namespace android {
+
+namespace camera3 {
+// For Capture request
+// metering region -> {fwk private key for metering region set, true}
+static std::unordered_map<uint32_t, std::pair<uint32_t, uint32_t>> kMeteringRegionsToCorrect = {
+    {ANDROID_CONTROL_AF_REGIONS,
+        {ANDROID_CONTROL_AF_REGIONS_SET, ANDROID_CONTROL_AF_REGIONS_SET_TRUE}},
+    {ANDROID_CONTROL_AE_REGIONS,
+        {ANDROID_CONTROL_AE_REGIONS_SET, ANDROID_CONTROL_AE_REGIONS_SET_TRUE}},
+    {ANDROID_CONTROL_AWB_REGIONS,
+        {ANDROID_CONTROL_AWB_REGIONS_SET,  ANDROID_CONTROL_AWB_REGIONS_SET_TRUE}}
+};
+
+UHRCropAndMeteringRegionMapper::UHRCropAndMeteringRegionMapper(const CameraMetadata &deviceInfo,
+        bool usePreCorrectedArray) {
+
+    if (usePreCorrectedArray) {
+        if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+                ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &mArrayWidth,
+                &mArrayHeight)) {
+            ALOGE("%s: Couldn't get pre correction active array size", __FUNCTION__);
+            return;
+        }
+        if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+                ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+                &mArrayWidthMaximumResolution, &mArrayHeightMaximumResolution)) {
+            ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
+                    __FUNCTION__);
+            return;
+        }
+    } else {
+        if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+                ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &mArrayWidth,
+                &mArrayHeight)) {
+            ALOGE("%s: Couldn't get active array size", __FUNCTION__);
+            return;
+        }
+        if (!SessionConfigurationUtils::getArrayWidthAndHeight(&deviceInfo,
+                ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+                &mArrayWidthMaximumResolution, &mArrayHeightMaximumResolution)) {
+            ALOGE("%s: Couldn't get maximum resolution active array size", __FUNCTION__);
+            return;
+        }
+
+    }
+
+    mIsValid = true;
+
+    ALOGV("%s: array size: %d x %d, full res array size: %d x %d,",
+            __FUNCTION__, mArrayWidth, mArrayHeight, mArrayWidthMaximumResolution,
+            mArrayHeightMaximumResolution);
+}
+
+void UHRCropAndMeteringRegionMapper::fixMeteringRegionsIfNeeded(CameraMetadata *request) {
+    if (request == nullptr) {
+      ALOGE("%s request is nullptr, can't fix crop region", __FUNCTION__);
+      return;
+    }
+    for (const auto &entry : kMeteringRegionsToCorrect) {
+        // Check if the metering region Set key is set to TRUE, we don't
+        // need to correct the metering regions.
+        camera_metadata_entry meteringRegionsSetEntry =
+                request->find(entry.second.first);
+        if (meteringRegionsSetEntry.count == 1 &&
+                meteringRegionsSetEntry.data.u8[0] == entry.second.second) {
+            // metering region set by client, doesn't need to be fixed.
+            continue;
+        }
+        camera_metadata_entry meteringRegionEntry = request->find(entry.first);
+        if (meteringRegionEntry.count % 5 != 0) {
+            ALOGE("%s: Metering region entry for tag %d does not have a valid number of entries, "
+                    "skipping", __FUNCTION__, (int)entry.first);
+            continue;
+        }
+        for (size_t j = 0; j < meteringRegionEntry.count; j += 5) {
+            int32_t *meteringRegionStart = meteringRegionEntry.data.i32 + j;
+            meteringRegionStart[0] = 0;
+            meteringRegionStart[1] = 0;
+            meteringRegionStart[2] = mArrayWidthMaximumResolution;
+            meteringRegionStart[3] = mArrayHeightMaximumResolution;
+        }
+    }
+}
+
+void UHRCropAndMeteringRegionMapper::fixCropRegionsIfNeeded(CameraMetadata *request) {
+    if (request == nullptr) {
+      ALOGE("%s request is nullptr, can't fix crop region", __FUNCTION__);
+      return;
+    }
+    // Check if the scalerCropRegionSet key is set to TRUE, we don't
+    // need to correct the crop region.
+    camera_metadata_entry cropRegionSetEntry =
+            request->find(ANDROID_SCALER_CROP_REGION_SET);
+    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.
+        return;
+    }
+    camera_metadata_entry_t cropRegionEntry = request->find(ANDROID_SCALER_CROP_REGION);
+    if (cropRegionEntry.count == 4) {
+        cropRegionEntry.data.i32[0] = 0;
+        cropRegionEntry.data.i32[1] = 0;
+        cropRegionEntry.data.i32[2] = mArrayWidthMaximumResolution;
+        cropRegionEntry.data.i32[3] = mArrayHeightMaximumResolution;
+    }
+}
+
+status_t UHRCropAndMeteringRegionMapper::updateCaptureRequest(CameraMetadata* request) {
+    if (request == nullptr) {
+        ALOGE("%s Invalid request, request is nullptr", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    if (!mIsValid) {
+        ALOGE("%s UHRCropAndMeteringRegionMapper didn't initialize correctly", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    camera_metadata_entry sensorPixelModeEntry = request->find(ANDROID_SENSOR_PIXEL_MODE);
+
+    // Check if this is max resolution capture, if not, we don't need to do
+    // anything.
+    if (sensorPixelModeEntry.count != 0) {
+        int32_t sensorPixelMode = sensorPixelModeEntry.data.u8[0];
+        if (sensorPixelMode != ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) {
+            // Correction not needed for default mode requests.
+           return OK;
+        }
+    } else {
+        // sensor pixel mode not set -> default sensor pixel mode request, which
+        // doesn't need correction.
+        return OK;
+    }
+
+    fixCropRegionsIfNeeded(request);
+    fixMeteringRegionsIfNeeded(request);
+    return OK;
+}
+
+} // namespace camera3
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h
new file mode 100644
index 0000000..a026e6d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/UHRCropAndMeteringRegionMapper.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_UHRCROP_REGIONS_MAPPER_H
+#define ANDROID_SERVERS_UHRCROP_REGIONS_MAPPER_H
+
+#include <utils/Errors.h>
+#include <array>
+
+#include "camera/CameraMetadata.h"
+
+namespace android {
+
+namespace camera3 {
+
+/**
+ * Utilities to transform SCALER_CROP_REGION and metering regions for ultra high
+ * resolution sensors.
+ */
+class UHRCropAndMeteringRegionMapper {
+ public:
+    UHRCropAndMeteringRegionMapper() = default;
+    UHRCropAndMeteringRegionMapper(const CameraMetadata &deviceInfo, bool usePreCorrectionArray);
+
+    /**
+     * Adjust capture request assuming rotate and crop AUTO is enabled
+     */
+    status_t updateCaptureRequest(CameraMetadata *request);
+
+ private:
+
+    void fixCropRegionsIfNeeded(CameraMetadata *request);
+    void fixMeteringRegionsIfNeeded(CameraMetadata *request);
+
+    int32_t mArrayWidth = 0;
+    int32_t mArrayHeight = 0;
+    int32_t mArrayWidthMaximumResolution = 0;
+    int32_t mArrayHeightMaximumResolution = 0;
+    bool mIsValid = false;
+}; // class UHRCropAndMeteringRegionMapper
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
index 1a39510..7ec0956 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.cpp
@@ -129,20 +129,6 @@
     return OK;
 }
 
-static bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
-        int32_t arrayTag, int32_t *width, int32_t *height) {
-    if (width == nullptr || height == nullptr) {
-        ALOGE("%s: width / height nullptr", __FUNCTION__);
-        return false;
-    }
-    camera_metadata_ro_entry_t entry;
-    entry = deviceInfo->find(arrayTag);
-    if (entry.count != 4) return false;
-    *width = entry.data.i32[2];
-    *height = entry.data.i32[3];
-    return true;
-}
-
 ZoomRatioMapper::ZoomRatioMapper(const CameraMetadata* deviceInfo,
         bool supportNativeZoomRatio, bool usePrecorrectArray) {
     initRemappedKeys();
@@ -156,13 +142,13 @@
     int32_t activeMaximumResolutionW = 0;
     int32_t activeMaximumResolutionH = 0;
 
-    if (!getArrayWidthAndHeight(deviceInfo, ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
-            &arrayW, &arrayH)) {
+    if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
+            ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, &arrayW, &arrayH)) {
         ALOGE("%s: Couldn't get pre correction active array size", __FUNCTION__);
         return;
     }
-     if (!getArrayWidthAndHeight(deviceInfo, ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
-            &activeW, &activeH)) {
+     if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
+            ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &activeW, &activeH)) {
         ALOGE("%s: Couldn't get active array size", __FUNCTION__);
         return;
     }
@@ -170,14 +156,14 @@
     bool isUltraHighResolutionSensor =
             camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(*deviceInfo);
     if (isUltraHighResolutionSensor) {
-        if (!getArrayWidthAndHeight(deviceInfo,
+        if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
                 ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
                 &arrayMaximumResolutionW, &arrayMaximumResolutionH)) {
             ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
                     __FUNCTION__);
             return;
         }
-         if (!getArrayWidthAndHeight(deviceInfo,
+         if (!SessionConfigurationUtils::getArrayWidthAndHeight(deviceInfo,
                 ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
                 &activeMaximumResolutionW, &activeMaximumResolutionH)) {
             ALOGE("%s: Couldn't get maximum resolution pre correction active array size",
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 454c05f..a239c81 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -142,19 +142,19 @@
         case ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:
             return ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:
-            return ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS;
+            return ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:
             return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:
             return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:
-            return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS;
+            return ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:
             return ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:
             return ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS:
-            return ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS;
+            return ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION;
         case ANDROID_SENSOR_OPAQUE_RAW_SIZE:
             return ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION;
         case ANDROID_LENS_INTRINSIC_CALIBRATION:
@@ -169,6 +169,19 @@
     return -1;
 }
 
+bool SessionConfigurationUtils::getArrayWidthAndHeight(const CameraMetadata *deviceInfo,
+        int32_t arrayTag, int32_t *width, int32_t *height) {
+    if (width == nullptr || height == nullptr) {
+        ALOGE("%s: width / height nullptr", __FUNCTION__);
+        return false;
+    }
+    camera_metadata_ro_entry_t entry;
+    entry = deviceInfo->find(arrayTag);
+    if (entry.count != 4) return false;
+    *width = entry.data.i32[2];
+    *height = entry.data.i32[3];
+    return true;
+}
 
 StreamConfigurationPair
 SessionConfigurationUtils::getStreamConfigurationPair(const CameraMetadata &staticInfo) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 1fbaa69..192e241 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -85,6 +85,9 @@
             android_dataspace dataSpace, const CameraMetadata& info, bool maxResolution,
             /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
 
+    static bool getArrayWidthAndHeight(const CameraMetadata *deviceInfo, int32_t arrayTag,
+            int32_t *width, int32_t *height);
+
     //check if format is not custom format
     static bool isPublicFormat(int32_t format);