cameraserver: Add support for session specific hal buffer manager switches

With ICameraDeviceSession V3, it is possible for HALs to toggle HAL
buffer manager on and off depending on the session configuration.
Add support to cameraserver to switch HAL buffer manager behavior
for the session - depending on what the HAL decides.

Bug: 311263114

Test: Use GCA on device not advertising session hal buffer manager
Test: Camera CTS on cuttlefish

Change-Id: Ie7948a24e54bb920f49cf0c0ce61f42a4c8d09f7
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1e9f60d..0159b9f 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -100,7 +100,7 @@
         "android.frameworks.cameraservice.service-V2-ndk",
         "android.frameworks.cameraservice.device-V2-ndk",
         "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@2.4",
         "android.hardware.camera.provider@2.5",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6765c1d..8006ee1 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -54,6 +54,7 @@
 #include <android-base/properties.h>
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <com_android_internal_camera_flags.h>
 
 #include "CameraService.h"
 #include "aidl/android/hardware/graphics/common/Dataspace.h"
@@ -76,6 +77,7 @@
 using namespace android::camera3;
 using namespace android::hardware::camera;
 
+namespace flags = com::android::internal::camera::flags;
 namespace android {
 
 Camera3Device::Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
@@ -2545,6 +2547,7 @@
     }
 
     config.streams = streams.editArray();
+    config.use_hal_buf_manager = mUseHalBufManager;
 
     // Do the HAL configuration; will potentially touch stream
     // max_buffers, usage, and priv fields, as well as data_space and format
@@ -2568,7 +2571,22 @@
                 strerror(-res), res);
         return res;
     }
-
+    if (flags::session_hal_buf_manager()) {
+        bool prevSessionHalBufManager = mUseHalBufManager;
+        // It is possible that configureStreams() changed config.use_hal_buf_manager
+        mUseHalBufManager = config.use_hal_buf_manager;
+        if (prevSessionHalBufManager && !mUseHalBufManager) {
+            mRequestBufferSM.deInit();
+        } else if (!prevSessionHalBufManager && mUseHalBufManager) {
+            res = mRequestBufferSM.initialize(mStatusTracker);
+            if (res != OK) {
+                SET_ERR_L("%s: Camera %s: RequestBuffer State machine couldn't be initialized!",
+                          __FUNCTION__, mId.c_str());
+                return res;
+            }
+        }
+        mRequestThread->setHalBufferManager(mUseHalBufManager);
+    }
     // Finish all stream configuration immediately.
     // TODO: Try to relax this later back to lazy completion, which should be
     // faster
@@ -3278,6 +3296,10 @@
     mDoPauseSignal.signal();
 }
 
+void Camera3Device::RequestThread::setHalBufferManager(bool enabled) {
+    mUseHalBufManager = enabled;
+}
+
 status_t Camera3Device::RequestThread::waitUntilRequestProcessed(
         int32_t requestId, nsecs_t timeout) {
     ATRACE_CALL();
@@ -5231,6 +5253,27 @@
     return OK;
 }
 
+status_t Camera3Device::RequestBufferStateMachine::deInit() {
+    std::lock_guard<std::mutex> lock(mLock);
+    sp<StatusTracker> statusTracker = mStatusTracker.promote();
+    if (statusTracker == nullptr) {
+        ALOGE("%s: statusTracker is null", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if (mRequestBufferStatusId == StatusTracker::NO_STATUS_ID) {
+        ALOGE("%s: RequestBufferStateMachine not initialized", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    statusTracker->removeComponent(mRequestBufferStatusId);
+    // Bring back to de-initialized state
+    mRequestBufferStatusId = StatusTracker::NO_STATUS_ID;
+    mRequestThreadPaused = true;
+    mInflightMapEmpty = true;
+    mRequestBufferOngoing = false;
+    mSwitchedToOffline = false;
+    return OK;
+}
+
 bool Camera3Device::RequestBufferStateMachine::startRequestBuffer() {
     std::lock_guard<std::mutex> lock(mLock);
     if (mStatus == RB_STATUS_READY || mStatus == RB_STATUS_PENDING_STOP) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d812c01..bde7e1b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -543,7 +543,7 @@
 
         uint32_t mNextStreamConfigCounter = 1;
 
-        const bool mUseHalBufManager;
+        bool mUseHalBufManager = false;
         bool mIsReconfigurationQuerySupported;
 
         const bool mSupportOfflineProcessing;
@@ -942,6 +942,13 @@
         void     setPaused(bool paused);
 
         /**
+         * Set Hal buffer manager behavior
+         * @param enabled Whether HAL buffer manager is enabled for the current session.
+         *
+         */
+        void setHalBufferManager(bool enabled);
+
+        /**
          * Wait until thread processes the capture request with settings'
          * android.request.id == requestId.
          *
@@ -1181,7 +1188,7 @@
 
         std::map<int32_t, std::set<std::string>> mGroupIdPhysicalCameraMap;
 
-        const bool         mUseHalBufManager;
+        bool               mUseHalBufManager = false;
         const bool         mSupportCameraMute;
         const bool         mOverrideToPortrait;
         const bool         mSupportSettingsOverride;
@@ -1372,7 +1379,7 @@
 
     // Whether HAL request buffers through requestStreamBuffers API
     bool mUseHalBufManager = false;
-
+    bool mSessionHalBufManager = false;
     // Lock to ensure requestStreamBuffers() callbacks are serialized
     std::mutex mRequestBufferInterfaceLock;
 
@@ -1408,6 +1415,8 @@
       public:
         status_t initialize(sp<camera3::StatusTracker> statusTracker);
 
+        status_t deInit();
+
         // Return if the state machine currently allows for requestBuffers
         // If the state allows for it, mRequestBufferOngoing will be set to true
         // and caller must call endRequestBuffer() later to unset the flag
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 1191f05..22f97bf 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -106,6 +106,13 @@
     return res;
 }
 
+void Camera3SharedOutputStream::setHalBufferManager(bool enabled) {
+    Mutex::Autolock l(mLock);
+    mUseHalBufManager = enabled;
+    if (mStreamSplitter != nullptr) {
+        mStreamSplitter->setHalBufferManager(enabled);
+    }
+}
 
 status_t Camera3SharedOutputStream::notifyBufferReleased(ANativeWindowBuffer *anwBuffer) {
     Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index c2ff20e..90914d4 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -51,6 +51,8 @@
 
     virtual ~Camera3SharedOutputStream();
 
+    void setHalBufferManager(bool enabled) override;
+
     virtual status_t notifyBufferReleased(ANativeWindowBuffer *buffer);
 
     virtual bool isConsumerConfigurationDeferred(size_t surface_id) const;
@@ -85,7 +87,7 @@
 
     // Whether HAL is in control for buffer management. Surface sharing behavior
     // depends on this flag.
-    const bool mUseHalBufManager;
+    bool mUseHalBufManager;
 
     // Pair of an output Surface and its unique ID
     typedef std::pair<sp<Surface>, size_t> SurfaceUniqueId;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 2bfaaab..f06ccf3 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -414,6 +414,11 @@
     virtual status_t setStatusTracker(sp<StatusTracker> statusTracker);
 
     /**
+     * Toggle the state of hal buffer manager
+     */
+    virtual void setHalBufferManager(bool /*enabled*/) {/* No-op */ }
+
+    /**
      * Disconnect stream from its non-HAL endpoint. After this,
      * start/finishConfiguration must be called before the stream can be used
      * again. This cannot be called if the stream has outstanding dequeued
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 8175eb5..255b4f2 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -184,6 +184,11 @@
     return res;
 }
 
+void Camera3StreamSplitter::setHalBufferManager(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+    mUseHalBufManager = enabled;
+}
+
 status_t Camera3StreamSplitter::addOutputLocked(size_t surfaceId, const sp<Surface>& outputQueue) {
     ATRACE_CALL();
     if (outputQueue == nullptr) {
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 639353c..1feb4a0 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -94,6 +94,8 @@
     // Disconnect the buffer queue from output surfaces.
     void disconnect();
 
+    void setHalBufferManager(bool enabled);
+
 private:
     // From IConsumerListener
     //
@@ -291,7 +293,7 @@
 
     std::string mConsumerName;
 
-    const bool mUseHalBufManager;
+    bool mUseHalBufManager;
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
index 665ac73..a7bd312 100644
--- a/services/camera/libcameraservice/device3/InFlightRequest.h
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -34,6 +34,7 @@
     camera_stream_t **streams;
     uint32_t operation_mode;
     bool input_is_multi_resolution;
+    bool use_hal_buf_manager = false;
 } camera_stream_configuration_t;
 
 typedef struct camera_capture_request {
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 272c390..c90fad2 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -49,12 +49,14 @@
 #include <utils/Timers.h>
 #include <cutils/properties.h>
 
+#include <aidl/android/hardware/camera/device/ICameraDeviceSession.h>
 #include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
 #include <aidlcommonsupport/NativeHandle.h>
 #include <android-base/properties.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 #include <camera/StringUtils.h>
+#include <com_android_internal_camera_flags.h>
 
 #include "utils/CameraTraces.h"
 #include "mediautils/SchedulingPolicyService.h"
@@ -82,6 +84,9 @@
 using aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
 using aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
 
+namespace flags = com::android::internal::camera::flags;
+
+const int32_t AIDL_DEVICE_SESSION_V3 = 3;
 namespace android {
 
 RequestAvailableDynamicRangeProfilesMap
@@ -288,6 +293,8 @@
     if (bufMgrMode.count > 0) {
         mUseHalBufManager = (bufMgrMode.data.u8[0] ==
                 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+        mSessionHalBufManager = (bufMgrMode.data.u8[0] ==
+                ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_SESSION_CONFIGURABLE);
     }
 
     camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
@@ -298,7 +305,9 @@
         }
     }
 
-    mInterface = new AidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
+    mInterface =
+            new AidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing,
+                    mSessionHalBufManager);
 
     std::string providerType;
     mVendorTagId = manager->getProviderTagIdLocked(mId);
@@ -713,21 +722,25 @@
 AidlCamera3Device::AidlHalInterface::AidlHalInterface(
             std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession> &session,
             std::shared_ptr<AidlRequestMetadataQueue> queue,
-            bool useHalBufManager, bool supportOfflineProcessing) :
+            bool useHalBufManager, bool supportOfflineProcessing,
+            bool supportSessionHalBufManager) :
         HalInterface(useHalBufManager, supportOfflineProcessing),
         mAidlSession(session),
-        mRequestMetadataQueue(queue) { }
+        mRequestMetadataQueue(queue),
+        mSupportSessionHalBufManager(supportSessionHalBufManager) { }
 
 AidlCamera3Device::AidlHalInterface::AidlHalInterface(
             std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession>
                     &deviceSession,
             std::shared_ptr<aidl::android::hardware::camera::device::ICameraInjectionSession>
                     &injectionSession, std::shared_ptr<AidlRequestMetadataQueue> queue,
-            bool useHalBufManager, bool supportOfflineProcessing) :
+            bool useHalBufManager, bool supportOfflineProcessing,
+            bool supportSessionHalBufManager) :
         HalInterface(useHalBufManager, supportOfflineProcessing),
         mAidlSession(deviceSession),
         mAidlInjectionSession(injectionSession),
-        mRequestMetadataQueue(queue) { }
+        mRequestMetadataQueue(queue),
+        mSupportSessionHalBufManager(supportSessionHalBufManager) { }
 
 bool AidlCamera3Device::AidlHalInterface::valid() {
     return (mAidlSession != nullptr);
@@ -979,14 +992,34 @@
     requestedConfiguration.streamConfigCounter = mNextStreamConfigCounter++;
     requestedConfiguration.multiResolutionInputImage = config->input_is_multi_resolution;
     requestedConfiguration.logId = logId;
-    auto err = mAidlSession->configureStreams(requestedConfiguration, &finalConfiguration);
+    ndk::ScopedAStatus err = ndk::ScopedAStatus::ok();
+    camera::device::ConfigureStreamsRet configureStreamsRet;
+    if (flags::session_hal_buf_manager()) {
+        int32_t interfaceVersion = 0;
+        err = mAidlSession->getInterfaceVersion(&interfaceVersion);
+        if (!err.isOk()) {
+            ALOGE("%s: Transaction error getting interface version: %s", __FUNCTION__,
+                    err.getMessage());
+            return AidlProviderInfo::mapToStatusT(err);
+        }
+        if (interfaceVersion >= AIDL_DEVICE_SESSION_V3 && mSupportSessionHalBufManager) {
+            err = mAidlSession->configureStreamsV2(requestedConfiguration, &configureStreamsRet);
+            finalConfiguration = std::move(configureStreamsRet.halStreams);
+        } else {
+            err = mAidlSession->configureStreams(requestedConfiguration, &finalConfiguration);
+        }
+    } else {
+        err = mAidlSession->configureStreams(requestedConfiguration, &finalConfiguration);
+    }
     if (!err.isOk()) {
         ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
         return AidlProviderInfo::mapToStatusT(err);
     }
-
+    if (flags::session_hal_buf_manager() && mSupportSessionHalBufManager) {
+        mUseHalBufManager = configureStreamsRet.enableHalBufferManager;
+        config->use_hal_buf_manager = configureStreamsRet.enableHalBufferManager;
+    }
     // And convert output stream configuration from AIDL
-
     for (size_t i = 0; i < config->num_streams; i++) {
         camera3::camera_stream_t *dst = config->streams[i];
         int streamId = Camera3Stream::cast(dst)->getId();
@@ -1055,6 +1088,10 @@
             }
             dstStream->setUsage(
                     mapProducerToFrameworkUsage(src.producerUsage));
+
+            if (flags::session_hal_buf_manager()) {
+                dstStream->setHalBufferManager(mUseHalBufManager);
+            }
         }
         dst->max_buffers = src.maxBuffers;
     }
@@ -1548,7 +1585,7 @@
 
     mInjectedCamHalInterface =
             new AidlHalInterface(deviceSession, injectionSession, queue, parent->mUseHalBufManager,
-                       parent->mSupportOfflineProcessing);
+                       parent->mSupportOfflineProcessing, parent->mSessionHalBufManager);
     if (mInjectedCamHalInterface == nullptr) {
         ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
         return DEAD_OBJECT;
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index 21813d4..90e2f97 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -72,19 +72,22 @@
             /*out*/ sp<CameraOfflineSessionBase>* /*session*/) override;
 
     status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags) override;
+
     class AidlHalInterface : public Camera3Device::HalInterface {
      public:
         AidlHalInterface(std::shared_ptr<
                 aidl::android::hardware::camera::device::ICameraDeviceSession> &session,
                 std::shared_ptr<AidlRequestMetadataQueue> queue,
-                bool useHalBufManager, bool supportOfflineProcessing);
+                bool useHalBufManager, bool supportOfflineProcessing,
+                bool supportSessionHalBufManager);
         AidlHalInterface(
                 std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession>
                     &deviceSession,
                 std::shared_ptr<
                 aidl::android::hardware::camera::device::ICameraInjectionSession> &injectionSession,
                 std::shared_ptr<AidlRequestMetadataQueue> queue,
-                bool useHalBufManager, bool supportOfflineProcessing);
+                bool useHalBufManager, bool supportOfflineProcessing,
+                bool supportSessionHalBufManager);
 
         virtual IPCTransport getTransportType() const override {return IPCTransport::AIDL; }
 
@@ -153,6 +156,7 @@
                 /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
 
         std::shared_ptr<AidlRequestMetadataQueue> mRequestMetadataQueue;
+        bool mSupportSessionHalBufManager = false;
     }; // class AidlHalInterface
 
     /**
diff --git a/services/camera/virtualcamera/Android.bp b/services/camera/virtualcamera/Android.bp
index c8fa84e..870b9d5 100644
--- a/services/camera/virtualcamera/Android.bp
+++ b/services/camera/virtualcamera/Android.bp
@@ -27,7 +27,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",
         "libaidlcommonsupport",
diff --git a/services/camera/virtualcamera/VirtualCameraSession.h b/services/camera/virtualcamera/VirtualCameraSession.h
index 50962e5..8bf66bc 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.h
+++ b/services/camera/virtualcamera/VirtualCameraSession.h
@@ -64,6 +64,12 @@
       std::vector<::aidl::android::hardware::camera::device::HalStream>*
           _aidl_return) override EXCLUDES(mLock);
 
+  ndk::ScopedAStatus configureStreamsV2(
+      const ::aidl::android::hardware::camera::device::StreamConfiguration&,
+      ::aidl::android::hardware::camera::device::ConfigureStreamsRet*) override {
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+  };
+
   ndk::ScopedAStatus constructDefaultRequestSettings(
       ::aidl::android::hardware::camera::device::RequestTemplate in_type,
       ::aidl::android::hardware::camera::device::CameraMetadata* _aidl_return)