camera: Add support for toggling HAL buffer manager as a result of session configuration

Currently, whether the HAL buffer manager is used or not is decided
based on the presence of a static camera characteristics key -
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION. This behavior cannot
be toggled depending on stream configuration / session parameters.

The HAL buffer manager does reduce memory consumption at the cost of
extra IPC calls, which may not be always desirable.

Therefore, a new API - 'configureStreamsV2()' is introduced to give the
camera HAL the ability to inform the camera framework whether it must
use the HAL buffer manager for the particular session configured.

Bug: 311263114

Test: VtsAidlHalCameraProvider_TargetTest on cuttlefish
Test: builds

Change-Id: Ibce6d64c3c9cc8e0ebc40522369291d03053cce2
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 1a665fb..4115c65 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -11,7 +11,7 @@
     name: "android.hardware.camera.device",
     vendor_available: true,
     srcs: ["android/hardware/camera/device/*.aidl"],
-    frozen: true,
+    frozen: false,
     stability: "vintf",
     imports: [
         "android.hardware.common-V2",
diff --git a/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ConfigureStreamsRet.aidl b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ConfigureStreamsRet.aidl
new file mode 100644
index 0000000..5535a30
--- /dev/null
+++ b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ConfigureStreamsRet.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.camera.device;
+@VintfStability
+parcelable ConfigureStreamsRet {
+  android.hardware.camera.device.HalStream[] halStreams;
+  boolean enableHalBufferManager = false;
+}
diff --git a/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ICameraDeviceSession.aidl b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ICameraDeviceSession.aidl
index 2196d37..b6ae734 100644
--- a/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ICameraDeviceSession.aidl
+++ b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/ICameraDeviceSession.aidl
@@ -45,4 +45,5 @@
   oneway void signalStreamFlush(in int[] streamIds, in int streamConfigCounter);
   android.hardware.camera.device.ICameraOfflineSession switchToOffline(in int[] streamsToKeep, out android.hardware.camera.device.CameraOfflineSessionInfo offlineSessionInfo);
   void repeatingRequestEnd(in int frameNumber, in int[] streamIds);
+  android.hardware.camera.device.ConfigureStreamsRet configureStreamsV2(in android.hardware.camera.device.StreamConfiguration requestedConfiguration);
 }
diff --git a/camera/device/aidl/android/hardware/camera/device/ConfigureStreamsRet.aidl b/camera/device/aidl/android/hardware/camera/device/ConfigureStreamsRet.aidl
new file mode 100644
index 0000000..8f462ec
--- /dev/null
+++ b/camera/device/aidl/android/hardware/camera/device/ConfigureStreamsRet.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package android.hardware.camera.device;
+
+import android.hardware.camera.device.HalStream;
+
+/**
+ * ConfigureStreamsRet.
+ *
+ * Parcelable returned by the 'configureStreamsV2' call.
+ * This contains information which informs the camera framework
+ * about properties of each stream configured and also whether the
+ * the hal buffer manager must be used for the session configured.
+ */
+@VintfStability
+parcelable ConfigureStreamsRet {
+    /**
+     * A vector of HalStream Parcelables, which contain information
+     * about the stream parameters desired by the HAL such as usage flags,
+     * overridden format, maximum buffers etc.
+     */
+    HalStream[] halStreams;
+    /**
+     * A boolean informing the camera framework whether the HAL buffer manager
+     * must be used for the session configured.
+     */
+    boolean enableHalBufferManager = false;
+}
diff --git a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
index 885c71a..ffc1a11 100644
--- a/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/ICameraDeviceSession.aidl
@@ -20,6 +20,7 @@
 import android.hardware.camera.device.CameraMetadata;
 import android.hardware.camera.device.CameraOfflineSessionInfo;
 import android.hardware.camera.device.CaptureRequest;
+import android.hardware.camera.device.ConfigureStreamsRet;
 import android.hardware.camera.device.HalStream;
 import android.hardware.camera.device.ICameraOfflineSession;
 import android.hardware.camera.device.RequestTemplate;
@@ -88,6 +89,13 @@
      * with processCaptureResult (and its respective releaseFence has been
      * signaled) the framework may free or reuse it at any time.
      *
+     * This method wil only be called by the framework if
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION is either not advertised or is
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_AIDL. If the value of
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION is
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE, configureStreamsV2
+     * will be called instead.
+     *
      * ------------------------------------------------------------------------
      *
      * Preconditions:
@@ -386,8 +394,8 @@
      *          error.
      * @return true in case the stream reconfiguration is required, false otherwise.
      */
-    boolean isReconfigurationRequired(in CameraMetadata oldSessionParams,
-                                      in CameraMetadata newSessionParams);
+    boolean isReconfigurationRequired(
+            in CameraMetadata oldSessionParams, in CameraMetadata newSessionParams);
 
     /**
      * processCaptureRequest:
@@ -576,4 +584,29 @@
      */
     void repeatingRequestEnd(in int frameNumber, in int[] streamIds);
 
+    /**
+     *
+     * configureStreamsV2:
+     *
+     * Performs the same function as 'configureStreams'. This function returns a
+     * 'ConfigureStreamsRet' Parcelable. This tells the framework about the desired stream
+     * parameters such as usage flags, maximum buffers, overridden format etc. It also informs
+     * camera framework whether the HAL will use the HAL buffer manager APIs 'requestStreamBuffers'
+     * and 'returnStreamBuffers' to request and return buffers to the framework.
+     *
+     * This method is only supported if
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION is
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE. It must not be
+     * called by the camera framework if it isn't supported. That is, the framework will only
+     * ever call one of 'configureStreams' or 'configureStreamsV2' depending on the value of
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION.
+     *
+     * @param requestedConfiguration The stream configuration requested by the camera framework to
+     *        be configured by the camera HAL.
+     * @return A ConfigureStreamsRet Parcelable containing a vector of HalStreams and a boolean
+     *         specifying whether the HAL buffer manager must be used for this session
+     *         configuration.
+     *
+     */
+    ConfigureStreamsRet configureStreamsV2(in StreamConfiguration requestedConfiguration);
 }
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
index 7303ff5..2c31cff 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
@@ -39,4 +39,5 @@
 @Backing(type="int") @VintfStability
 enum InfoSupportedBufferManagementVersion {
   ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_AIDL_DEVICE,
+  ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE,
 }
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
index 9522377..964d079 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/InfoSupportedBufferManagementVersion.aidl
@@ -30,4 +30,5 @@
 @Backing(type="int")
 enum InfoSupportedBufferManagementVersion {
     ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_AIDL_DEVICE,
+    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE,
 }
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index 35ec976..1199b18 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -14,7 +14,7 @@
         "android/hardware/camera/provider/*.aidl",
     ],
     imports: [
-        "android.hardware.camera.device-V2",
+        "android.hardware.camera.device-V3",
         "android.hardware.camera.common-V1",
     ],
     frozen: true,
@@ -38,7 +38,7 @@
         {
             version: "2",
             imports: [
-                "android.hardware.camera.device-V2",
+                "android.hardware.camera.device-V3",
                 "android.hardware.camera.common-V1",
             ],
         },
diff --git a/camera/provider/aidl/vts/Android.bp b/camera/provider/aidl/vts/Android.bp
index cfcaec5..398bca1 100644
--- a/camera/provider/aidl/vts/Android.bp
+++ b/camera/provider/aidl/vts/Android.bp
@@ -60,7 +60,7 @@
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
         "android.hardware.camera.common-V1-ndk",
-        "android.hardware.camera.device-V2-ndk",
+        "android.hardware.camera.device-V3-ndk",
         "android.hardware.camera.metadata-V2-ndk",
         "android.hardware.camera.provider-V2-ndk",
         "android.hidl.allocator@1.0",
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index e5bf637..7f4f6bc 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -1350,13 +1350,17 @@
     bool hasHalBufferManager =
             (0 == retcode && 1 == entry.count &&
              entry.data.i32[0] == ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+    bool sessionHalBufferManager =
+            (0 == retcode && 1 == entry.count &&
+             entry.data.i32[0] ==
+                     ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     retcode = find_camera_metadata_ro_entry(
             metadata, ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED, &entry);
     bool multiResolutionStreamSupported =
             (0 == retcode && 1 == entry.count &&
              entry.data.u8[0] == ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE);
     if (multiResolutionStreamSupported) {
-        ASSERT_TRUE(hasHalBufferManager);
+        ASSERT_TRUE(hasHalBufferManager || sessionHalBufferManager);
     }
 
     std::string version, cameraId;
@@ -2440,6 +2444,28 @@
 
 }
 
+ndk::ScopedAStatus CameraAidlTest::configureStreams(std::shared_ptr<ICameraDeviceSession>& session,
+                                                    const StreamConfiguration& config,
+                                                    bool sessionHalBufferManager,
+                                                    bool* useHalBufManager,
+                                                    std::vector<HalStream>* halStreams) {
+    auto ret = ndk::ScopedAStatus::ok();
+    ConfigureStreamsRet aidl_return;
+    if (sessionHalBufferManager) {
+        ret = session->configureStreamsV2(config, &aidl_return);
+    } else {
+        ret = session->configureStreams(config, halStreams);
+    }
+    if (!ret.isOk()) {
+        return ret;
+    }
+    if (sessionHalBufferManager) {
+        *useHalBufManager = aidl_return.enableHalBufferManager;
+        *halStreams = std::move(aidl_return.halStreams);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 void CameraAidlTest::configureSingleStream(
         const std::string& name, const std::shared_ptr<ICameraProvider>& provider,
         const AvailableStream* previewThreshold, uint64_t bufferUsage, RequestTemplate reqTemplate,
@@ -2494,11 +2520,15 @@
     ASSERT_NE(*session, nullptr);
 
     *useHalBufManager = false;
+    bool sessionHalBufferManager = false;
     status = find_camera_metadata_ro_entry(
             staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
     if ((0 == status) && (entry.count == 1)) {
         *useHalBufManager = (entry.data.u8[0] ==
                              ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+        sessionHalBufferManager =
+                (entry.data.u8[0] ==
+                 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     }
 
     outputPreviewStreams.clear();
@@ -2557,7 +2587,8 @@
         ASSERT_EQ(supported, true);
 
         std::vector<HalStream> halConfigs;
-        ret = (*session)->configureStreams(config, &halConfigs);
+        ret = configureStreams(*session, config, sessionHalBufferManager, useHalBufManager,
+                               &halConfigs);
         ALOGI("configureStreams returns status: %d:%d", ret.getExceptionCode(),
               ret.getServiceSpecificError());
         ASSERT_TRUE(ret.isOk());
@@ -2853,11 +2884,15 @@
     ASSERT_NE(*session, nullptr);
 
     *useHalBufManager = false;
+    bool sessionHalBufferManager = false;
     status = find_camera_metadata_ro_entry(
             staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
     if ((0 == status) && (entry.count == 1)) {
         *useHalBufManager = (entry.data.u8[0] ==
                              ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+        sessionHalBufferManager =
+                (entry.data.u8[0] ==
+                 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     }
 
     outputPreviewStreams.clear();
@@ -2912,7 +2947,9 @@
 
     config.streamConfigCounter = streamConfigCounter;
     std::vector<HalStream> halConfigs;
-    ret = (*session)->configureStreams(config, &halConfigs);
+    ret = configureStreams(*session, config, sessionHalBufferManager, useHalBufManager,
+                           &halConfigs);
+
     ASSERT_TRUE(ret.isOk());
     ASSERT_EQ(physicalIds.size(), halConfigs.size());
     *halStreams = halConfigs;
@@ -2992,11 +3029,15 @@
     ASSERT_NE(*session, nullptr);
 
     *useHalBufManager = false;
+    bool sessionHalBufferManager = false;
     status = find_camera_metadata_ro_entry(
             staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
     if ((0 == status) && (entry.count == 1)) {
         *useHalBufManager = (entry.data.u8[0] ==
                              ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+        sessionHalBufferManager =
+                (entry.data.u8[0] ==
+                 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     }
 
     outputStreams.clear();
@@ -3050,7 +3091,8 @@
     ASSERT_TRUE(ret.isOk());
     ASSERT_EQ(supported, true);
 
-    ret = (*session)->configureStreams(config, halStreams);
+    ret = configureStreams(*session, config, sessionHalBufferManager, useHalBufManager, halStreams);
+
     ASSERT_TRUE(ret.isOk());
 
     if (*useHalBufManager) {
@@ -3434,11 +3476,15 @@
     }
 
     *useHalBufManager = false;
+    bool sessionHalBufferManager = false;
     status = find_camera_metadata_ro_entry(
             staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
     if ((0 == status) && (entry.count == 1)) {
         *useHalBufManager = (entry.data.u8[0] ==
                              ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+        sessionHalBufferManager =
+                (entry.data.u8[0] ==
+                 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     }
 
     auto st = getJpegBufferSize(staticMeta, jpegBufferSize);
@@ -3491,7 +3537,8 @@
 
     StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE, CameraMetadata()};
 
-    (*session)->configureStreams(config, halStreams);
+    ret = configureStreams(*session, config, sessionHalBufferManager, useHalBufManager, halStreams);
+
     ASSERT_TRUE(ret.isOk());
 
     if (*useHalBufManager) {
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index 0ebd4ef..90639bb 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -64,6 +64,7 @@
 using ::aidl::android::hardware::camera::device::BufferRequestStatus;
 using ::aidl::android::hardware::camera::device::CameraMetadata;
 using ::aidl::android::hardware::camera::device::CaptureResult;
+using ::aidl::android::hardware::camera::device::ConfigureStreamsRet;
 using ::aidl::android::hardware::camera::device::ErrorCode;
 using ::aidl::android::hardware::camera::device::HalStream;
 using ::aidl::android::hardware::camera::device::ICameraDevice;
@@ -201,6 +202,11 @@
             int32_t* partialResultCount /*out*/, std::shared_ptr<DeviceCb>* outCb /*out*/,
             int32_t* jpegBufferSize /*out*/, bool* useHalBufManager /*out*/);
 
+    ndk::ScopedAStatus configureStreams(std::shared_ptr<ICameraDeviceSession>& session,
+                                        const StreamConfiguration& config,
+                                        bool sessionHalBufferManager, bool* useHalBufManager,
+                                        std::vector<HalStream>* halStreams);
+
     void configureStreams(
             const std::string& name, const std::shared_ptr<ICameraProvider>& provider,
             PixelFormat format, std::shared_ptr<ICameraDeviceSession>* session /*out*/,