Snap for 14805172 from eba1fb4f9c8072e6aaa8e4cb248147c1cf8e1ec8 to internal-android15-automotiveos-lts-release

Change-Id: I5a80e13dc5a69ef64ecb324682aee87110c3aab2
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index ce6c2d3..6431737 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -157,6 +157,7 @@
      *                     policy for default device context). Only virtual cameras would be exposed
      *                     only for custom policy and only real cameras would be exposed for default
      *                     policy.
+     * @param sharedMode Parameter specifying if the camera should be opened in shared mode.
      */
     ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
             @utf8InCpp String cameraId,
@@ -164,7 +165,8 @@
             int targetSdkVersion,
             int rotationOverride,
             in AttributionSourceState clientAttribution,
-            int devicePolicy);
+            int devicePolicy,
+            boolean sharedMode);
 
     /**
      * Add listener for changes to camera device and flashlight state.
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index 9c8c88a..c0fd50e 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -105,5 +105,6 @@
      * will receive such callbacks.
      */
     oneway void onCameraOpened(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId, int deviceId);
+    oneway void onCameraOpenedInSharedMode(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId, int deviceId, boolean primaryClient);
     oneway void onCameraClosed(@utf8InCpp String cameraId, int deviceId);
 }
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 58b19a3..49e9920 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -50,4 +50,15 @@
     oneway void onRepeatingRequestError(in long lastFrameNumber,
                                         in int repeatingRequestId);
     oneway void onRequestQueueEmpty();
+
+    /**
+     * Notify registered clients about client shared access priority changes when the camera device
+     * has been opened in shared mode.
+     *
+     * If the client priority changes from secondary to primary, then it can now
+     * create capture request and change the capture request parameters. If client priority
+     * changes from primary to secondary, that implies that another higher priority client is also
+     * accessing the camera in shared mode and is now the primary client.
+     */
+    oneway void onClientSharedAccessPriorityChanged(boolean primaryClient);
 }
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 8e1fcc0..30566c8 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -34,6 +34,20 @@
 
     SubmitInfo submitRequest(in CaptureRequest request, boolean streaming);
     SubmitInfo submitRequestList(in CaptureRequest[] requestList, boolean streaming);
+    /**
+     * When a camera device is opened in shared mode, only the primary client can change capture
+     * parameters and submit capture requests. Secondary clients can use the startStreaming API to
+     * provide the stream and surface IDs they want to stream on. If the primary client has an
+     * ongoing repeating request, camera service will attach these surfaces to it. Otherwise,
+     * camera service will create a default capture request with a preview template.
+     *
+     * @param streamIdxArray stream ids of the target surfaces
+     * @param surfaceIdxArray surface ids of the target surfaces
+     * @return SubmitInfo data structure containing the request id of the capture request and the
+     *         frame number of the last request, of the previous batch of repeating requests, if
+     *         any. If there is no previous  batch, the frame number returned will be -1.
+     */
+    SubmitInfo startStreaming(in int[] streamIdxArray, in int[] surfaceIdxArray);
 
     /**
      * Cancel the repeating request specified by requestId
@@ -68,6 +82,17 @@
     const int CONSTRAINED_HIGH_SPEED_MODE = 1;
 
     /**
+     * The shared operating mode for a camera device.
+     *
+     * <p>
+     * When in shared mode, the camera device can be opened and accessed by multiple applications
+     * simultaneously.
+     * </p>
+     *
+     */
+    const int SHARED_MODE = 2;
+
+    /**
      * Start of custom vendor modes
      */
     const int VENDOR_MODE_START = 0x8000;
@@ -194,4 +219,12 @@
      */
     ICameraOfflineSession switchToOffline(in ICameraDeviceCallbacks callbacks,
             in int[] offlineOutputIds);
+
+    /**
+     * Get the client status as primary or secondary when camera is opened in shared mode.
+     *
+     * @return true if this is primary client when camera is opened in shared mode.
+     *         false if another higher priority client with primary access is also using the camera.
+     */
+    boolean isPrimaryClient();
 }
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 2d1af32..cf386e9 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -32,6 +32,7 @@
 namespace android {
 
 const int OutputConfiguration::INVALID_ROTATION = -1;
+const int OutputConfiguration::ROTATION_0 = 0;
 const int OutputConfiguration::INVALID_SET_ID = -1;
 
 const std::vector<sp<IGraphicBufferProducer>>&
@@ -142,6 +143,29 @@
         mUsage(0) {
 }
 
+OutputConfiguration::OutputConfiguration(int surfaceType, int width, int height, int format,
+        int32_t colorSpace, int mirrorMode, bool useReadoutTimestamp, int timestampBase,
+        int dataspace, int64_t usage, int64_t streamusecase, std::string physicalCamId):
+        mRotation(ROTATION_0),
+        mSurfaceSetID(INVALID_SET_ID),
+        mSurfaceType(surfaceType),
+        mWidth(width),
+        mHeight(height),
+        mIsDeferred(false),
+        mIsShared(false),
+        mPhysicalCameraId(physicalCamId),
+        mIsMultiResolution(false),
+        mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
+        mColorSpace(colorSpace),
+        mStreamUseCase(streamusecase),
+        mTimestampBase(timestampBase),
+        mMirrorMode(mirrorMode),
+        mUseReadoutTimestamp(useReadoutTimestamp),
+        mFormat(format),
+        mDataspace(dataspace),
+        mUsage(usage){
+}
+
 OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID) {
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
index 5d85909..d8264df 100644
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
@@ -11,7 +11,7 @@
 
     <hal format="aidl">
         <name>android.frameworks.cameraservice.service</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>ICameraService</name>
             <instance>default</instance>
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 83ce39d..8cde55d 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -33,6 +33,7 @@
 class OutputConfiguration : public android::Parcelable {
 public:
 
+    static const int ROTATION_0;
     static const int INVALID_ROTATION;
     static const int INVALID_SET_ID;
     enum SurfaceType {
@@ -107,6 +108,9 @@
                         int surfaceSetID = INVALID_SET_ID,
                         int surfaceType = SURFACE_TYPE_UNKNOWN, int width = 0,
                         int height = 0, bool isShared = false);
+    OutputConfiguration(int surfaceType, int width, int height, int format, int32_t colorSpace,
+            int mirrorMode, bool useReadoutTimestamp,int timestampBase, int dataspace,
+            int64_t usage, int64_t streamusecase, std::string physicalCamId);
 
     bool operator == (const OutputConfiguration& other) const {
         return ( mRotation == other.mRotation &&
@@ -204,6 +208,28 @@
     bool sensorPixelModesUsedLessThan(const OutputConfiguration& other) const;
     bool gbpsLessThan(const OutputConfiguration& other) const;
     void addGraphicProducer(sp<IGraphicBufferProducer> gbp) {mGbps.push_back(gbp);}
+    bool sharedConfigEqual(const OutputConfiguration& other) const {
+        return (mRotation == other.mRotation &&
+                mSurfaceSetID == other.mSurfaceSetID &&
+                mSurfaceType == other.mSurfaceType &&
+                mWidth == other.mWidth &&
+                mHeight == other.mHeight &&
+                mIsDeferred == other.mIsDeferred &&
+                mIsShared == other.mIsShared &&
+                mPhysicalCameraId == other.mPhysicalCameraId &&
+                mIsMultiResolution == other.mIsMultiResolution &&
+                sensorPixelModesUsedEqual(other) &&
+                mDynamicRangeProfile == other.mDynamicRangeProfile &&
+                mColorSpace == other.mColorSpace &&
+                mStreamUseCase == other.mStreamUseCase &&
+                mTimestampBase == other.mTimestampBase &&
+                mMirrorMode == other.mMirrorMode &&
+                mUseReadoutTimestamp == other.mUseReadoutTimestamp &&
+                mFormat == other.mFormat &&
+                mDataspace == other.mDataspace &&
+                mUsage == other.mUsage);
+    }
+
 private:
     std::vector<sp<IGraphicBufferProducer>> mGbps;
     int                        mRotation;
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 379c0b5..508808f 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -79,6 +79,7 @@
     shared_libs: [
         "android.companion.virtual.virtualdevice_aidl-cpp",
         "android.companion.virtualdevice.flags-aconfig-cc",
+        "camera_platform_flags_c_lib",
         "framework-permission-aidl-cpp",
         "libandroid_runtime",
         "libbinder",
@@ -147,8 +148,8 @@
 
     shared_libs: [
         "android.frameworks.cameraservice.common-V1-ndk",
-        "android.frameworks.cameraservice.device-V2-ndk",
-        "android.frameworks.cameraservice.service-V2-ndk",
+        "android.frameworks.cameraservice.device-V3-ndk",
+        "android.frameworks.cameraservice.service-V3-ndk",
         "libbinder_ndk",
         "libcamera_metadata",
         "libcutils",
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 92de1e4..06ee714 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -177,6 +177,43 @@
 }
 
 EXPORT
+camera_status_t ACameraCaptureSessionShared_startStreaming(
+    ACameraCaptureSession* session,
+    /*optional*/ACameraCaptureSession_captureCallbacksV2* callbacks,
+    int numOutputWindows, ANativeWindow** windows,
+    /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    return startStreamingTemplate(session, callbacks, numOutputWindows, windows,
+            captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSessionShared_logicalCamera_startStreaming(
+    ACameraCaptureSession* session,
+    /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* callbacks,
+    int numOutputWindows, ANativeWindow** windows,
+    /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    return  startStreamingTemplate(session, callbacks, numOutputWindows, windows,
+            captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSessionShared_stopStreaming(ACameraCaptureSession* session) {
+    ATRACE_CALL();
+    if (session == nullptr) {
+        ALOGE("%s: Error: session is null", __FUNCTION__);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    return session->stopStreaming();
+}
+
+EXPORT
 camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* session,
         ACaptureSessionOutput* output) {
     ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraCaptureSession.inc b/camera/ndk/NdkCameraCaptureSession.inc
index 258e20d..3112735 100644
--- a/camera/ndk/NdkCameraCaptureSession.inc
+++ b/camera/ndk/NdkCameraCaptureSession.inc
@@ -68,3 +68,24 @@
 
     return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
 }
+
+template <class CallbackType>
+camera_status_t startStreamingTemplate(ACameraCaptureSession* session,
+    /*optional*/CallbackType* callbacks,
+    int numOutputWindows, ANativeWindow** windows,
+    /*optional*/int* captureSequenceId) {
+    ATRACE_CALL();
+    if (session == nullptr || windows == nullptr || numOutputWindows < 1) {
+        ALOGE("%s: Error: invalid input: session %p, numOutputWindows %d, windows %p",
+                __FUNCTION__, session, numOutputWindows, windows);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    if (session->isClosed()) {
+        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+        if (captureSequenceId) {
+            *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+        }
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+    return session->startStreaming(callbacks, numOutputWindows, windows, captureSequenceId);
+}
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index f2ec573..bc6b87a 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -59,6 +59,9 @@
                 __FUNCTION__, device, request);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
+    if (device->isSharedMode() && !device->isPrimaryClient()) {
+        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+    }
     switch (templateId) {
         case TEMPLATE_PREVIEW:
         case TEMPLATE_STILL_CAPTURE:
@@ -86,6 +89,9 @@
                 __FUNCTION__, device, request, physicalCameraIdList);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
+    if (device->isSharedMode() && !device->isPrimaryClient()) {
+        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+    }
     switch (templateId) {
         case TEMPLATE_PREVIEW:
         case TEMPLATE_STILL_CAPTURE:
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 1b3343e..e7a1c93 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -27,6 +27,8 @@
 #include "ndk_vendor/impl/ACameraManager.h"
 #else
 #include "impl/ACameraManager.h"
+#include <com_android_internal_camera_flags.h>
+namespace flags = com::android::internal::camera::flags;
 #endif
 #include "impl/ACameraMetadata.h"
 
@@ -159,6 +161,18 @@
 }
 
 EXPORT
+camera_status_t ACameraManager_isCameraDeviceSharingSupported(ACameraManager *mgr,
+        const char *cameraId, bool *isSharingSupported) {
+    ATRACE_CALL();
+    if (mgr == nullptr || cameraId == nullptr || isSharingSupported == nullptr) {
+        ALOGE("%s: invalid argument! mgr %p cameraId %p isSharingSupported %p",
+                __FUNCTION__, mgr, cameraId, isSharingSupported);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    return mgr->isCameraDeviceSharingSupported(cameraId, isSharingSupported);
+}
+
+EXPORT
 camera_status_t ACameraManager_getCameraCharacteristics(
         ACameraManager* mgr, const char* cameraId, ACameraMetadata** chars){
     ATRACE_CALL();
@@ -188,7 +202,27 @@
                 __FUNCTION__, mgr, cameraId, callback, device);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    return mgr->openCamera(cameraId, callback, device);
+    bool primaryClient;
+    return mgr->openCamera(cameraId, /*sharedMode*/false, callback, device, &primaryClient);
+}
+
+EXPORT
+camera_status_t ACameraManager_openSharedCamera(
+        ACameraManager* mgr, const char* cameraId, ACameraDevice_StateCallbacks* callback,
+        /*out*/ACameraDevice** device, /*out*/bool* primaryClient) {
+    ATRACE_CALL();
+    if (mgr == nullptr || cameraId == nullptr || callback == nullptr || device == nullptr ||
+            primaryClient == nullptr) {
+        ALOGE("%s: invalid argument! mgr %p cameraId %p callback %p device %p primary %p",
+                __FUNCTION__, mgr, cameraId, callback, device, primaryClient);
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    bool sharedMode;
+    camera_status_t status = mgr->isCameraDeviceSharingSupported(cameraId, &sharedMode);
+    if ((status != ACAMERA_OK) || !sharedMode) {
+         return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+    }
+    return mgr->openCamera(cameraId, /*sharedMode*/true, callback, device, primaryClient);
 }
 
 #ifdef __ANDROID_VNDK__
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index 449c0b4..8e7264a 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -96,6 +96,10 @@
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode() && !dev->isPrimaryClient()) {
+            dev->unlockDevice();
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->stopRepeatingLocked();
     }
@@ -103,6 +107,27 @@
     return ret;
 }
 
+camera_status_t ACameraCaptureSession::stopStreaming() {
+#ifdef __ANDROID_VNDK__
+    std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
+    sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->stopStreamingLocked();
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
 camera_status_t
 ACameraCaptureSession::abortCaptures() {
 #ifdef __ANDROID_VNDK__
@@ -114,10 +139,13 @@
         ALOGE("Error: Device associated with session %p has been closed!", this);
         return ACAMERA_ERROR_SESSION_CLOSED;
     }
-
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode() && !dev->isPrimaryClient()) {
+            dev->unlockDevice();
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->flushLocked(this);
     }
@@ -139,6 +167,10 @@
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode()) {
+            dev->unlockDevice();
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->updateOutputConfigurationLocked(output);
     }
@@ -160,6 +192,10 @@
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode()) {
+            dev->unlockDevice();
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->prepareLocked(window);
     }
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 0d7a2c1..eb13b96 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -150,6 +150,12 @@
 
     ACameraDevice* getDevice();
 
+    template<class T>
+    camera_status_t startStreaming(/*optional*/T* callbacks,
+            int numOutputWindows, ANativeWindow** windows, /*optional*/int* captureSequenceId);
+
+    camera_status_t stopStreaming();
+
   private:
     friend class android::acam::CameraDevice;
 
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
index da535f8..695eb37 100644
--- a/camera/ndk/impl/ACameraCaptureSession.inc
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -42,6 +42,9 @@
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode() && !dev->isPrimaryClient()) {
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->setRepeatingRequestsLocked(
                 this, cbs, numRequests, requests, captureSequenceId);
@@ -67,9 +70,37 @@
     camera_status_t ret;
     dev->lockDeviceForSessionOps();
     {
+        if (dev->isSharedMode() && !dev->isPrimaryClient()) {
+            return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+        }
         Mutex::Autolock _l(mSessionLock);
         ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
     }
     dev->unlockDevice();
     return ret;
 }
+
+template <class T>
+camera_status_t ACameraCaptureSession::startStreaming(
+        /*optional*/T* callbacks, int numOutputWindows, ANativeWindow** windows,
+	/*optional*/int* captureSequenceId)  {
+#ifdef __ANDROID_VNDK__
+    std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
+    sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->startStreamingLocked(this, callbacks, numOutputWindows, windows,
+                captureSequenceId);
+    }
+    dev->unlockDevice();
+    return ret;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 1fa71f4..cd59e5a 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -26,6 +26,9 @@
 #include "ACameraMetadata.h"
 #include "ACaptureRequest.h"
 #include "ACameraCaptureSession.h"
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
 
 ACameraDevice::~ACameraDevice() {
     mDevice->stopLooperAndDisconnect();
@@ -57,12 +60,13 @@
         const char* id,
         ACameraDevice_StateCallbacks* cb,
         sp<ACameraMetadata> chars,
-        ACameraDevice* wrapper) :
+        ACameraDevice* wrapper, bool sharedMode) :
         mCameraId(id),
         mAppCallbacks(*cb),
         mChars(chars),
         mServiceCallback(new ServiceCallback(this)),
         mWrapper(wrapper),
+        mSharedMode(sharedMode),
         mInError(false),
         mError(ACAMERA_OK),
         mIdle(true),
@@ -264,6 +268,28 @@
     }
 }
 
+camera_status_t CameraDevice::stopStreamingLocked() {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: camera is in closed or error state %d", __FUNCTION__, ret);
+        return ret;
+    }
+    ret = stopRepeatingLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: error when trying to stop streaming %d", __FUNCTION__, ret);
+        return ret;
+    }
+    for (auto& outputTarget : mPreviewRequestOutputs) {
+        ACameraOutputTarget_free(outputTarget);
+    }
+    mPreviewRequestOutputs.clear();
+    if (mPreviewRequest) {
+        ACaptureRequest_free(mPreviewRequest);
+        mPreviewRequest = nullptr;
+    }
+    return ACAMERA_OK;
+}
+
 camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
@@ -682,6 +708,11 @@
         if (ret != ACAMERA_OK) {
             return ret;
         }
+        // Surface sharing cannot be enabled when a camera has been opened
+        // in shared mode.
+        if (mSharedMode && outConfig.mIsShared) {
+            return ACAMERA_ERROR_INVALID_PARAMETER;
+        }
         outputSet.insert(std::make_pair(
                 anw, OutputConfiguration(iGBP, outConfig.mRotation, outConfig.mPhysicalCameraId,
                         OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
@@ -706,10 +737,14 @@
         return ret;
     }
 
-    ret = waitUntilIdleLocked();
-    if (ret != ACAMERA_OK) {
-        ALOGE("Camera device %s wait until idle failed, ret %d", getId(), ret);
-        return ret;
+    // If device is opened in shared mode, there can be multiple clients accessing the
+    // camera device. So do not wait for idle if the device is opened in shared mode.
+    if (!mSharedMode) {
+        ret = waitUntilIdleLocked();
+        if (ret != ACAMERA_OK) {
+            ALOGE("Camera device %s wait until idle failed, ret %d", getId(), ret);
+            return ret;
+        }
     }
 
     // Send onReady to previous session
@@ -970,6 +1005,7 @@
         case kWhatCaptureSeqAbort:
         case kWhatCaptureBufferLost:
         case kWhatPreparedCb:
+        case kWhatClientSharedAccessPriorityChanged:
             ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
             break;
         case kWhatCleanUpSessions:
@@ -1007,6 +1043,29 @@
             (*onDisconnected)(context, dev);
             break;
         }
+
+        case kWhatClientSharedAccessPriorityChanged:
+        {
+            ACameraDevice* dev;
+            found = msg->findPointer(kDeviceKey, (void**) &dev);
+            if (!found || dev == nullptr) {
+                ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+                return;
+            }
+            ACameraDevice_ClientSharedAccessPriorityChangedCallback
+                    onClientSharedAccessPriorityChanged;
+            found = msg->findPointer(kCallbackFpKey, (void**) &onClientSharedAccessPriorityChanged);
+            if (!found) {
+                ALOGE("%s: Cannot find onClientSharedAccessPriorityChanged!", __FUNCTION__);
+                return;
+            }
+            if (onClientSharedAccessPriorityChanged == nullptr) {
+                return;
+            }
+            (*onClientSharedAccessPriorityChanged)(context, dev, dev->isPrimaryClient());
+            break;
+        }
+
         case kWhatOnError:
         {
             ACameraDevice* dev;
@@ -1624,6 +1683,28 @@
 }
 
 binder::Status
+CameraDevice::ServiceCallback::onClientSharedAccessPriorityChanged(bool primaryClient) {
+    ALOGV("onClientSharedAccessPriorityChanged received. primaryClient = %d", primaryClient);
+    binder::Status ret = binder::Status::ok();
+    sp<CameraDevice> dev = mDevice.promote();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->isClosed() || dev->mRemote == nullptr) {
+        return ret;
+    }
+    dev->setPrimaryClient(primaryClient);
+    sp<AMessage> msg = new AMessage(kWhatClientSharedAccessPriorityChanged, dev->mHandler);
+    msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+    msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+    msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onClientSharedAccessPriorityChanged);
+    msg->post();
+
+    return binder::Status::ok();
+}
+
+binder::Status
 CameraDevice::ServiceCallback::onDeviceIdle() {
     ALOGV("Camera is now idle");
     binder::Status ret = binder::Status::ok();
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 2b9f327..39037bb 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -63,7 +63,7 @@
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
                   sp<ACameraMetadata> chars,
-                  ACameraDevice* wrapper);
+                  ACameraDevice* wrapper, bool sharedMode);
     ~CameraDevice();
 
     inline const char* getId() const { return mCameraId.c_str(); }
@@ -98,6 +98,7 @@
         binder::Status onRequestQueueEmpty() override;
         binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
                 int32_t stoppedSequenceId) override;
+        binder::Status onClientSharedAccessPriorityChanged(bool isPrimaryClient) override;
       private:
         const wp<CameraDevice> mDevice;
     };
@@ -113,6 +114,10 @@
     // Stop the looper thread and unregister the handler
     void stopLooperAndDisconnect();
 
+    void setPrimaryClient(bool isPrimary) {mIsPrimaryClient = isPrimary;};
+    bool isPrimaryClient() {return mIsPrimaryClient;};
+    bool isSharedMode() {return mSharedMode;};
+
   private:
     friend ACameraCaptureSession;
     camera_status_t checkCameraClosedOrErrorLocked() const;
@@ -128,6 +133,15 @@
 
     camera_status_t waitUntilIdleLocked();
 
+    camera_status_t stopStreamingLocked();
+
+    template<class T>
+    camera_status_t startStreamingLocked(ACameraCaptureSession* session,
+            /*optional*/T* callbacks,
+            int numOutputWindows, ANativeWindow** windows, /*optional*/int* captureSequenceId);
+
+    ACaptureRequest* mPreviewRequest = nullptr;
+    std::vector<ACameraOutputTarget*> mPreviewRequestOutputs;
 
     template<class T>
     camera_status_t captureLocked(sp<ACameraCaptureSession> session,
@@ -186,6 +200,8 @@
     const sp<ACameraMetadata> mChars;                 // Camera characteristics
     const sp<ServiceCallback> mServiceCallback;
     ACameraDevice* mWrapper;
+    bool mSharedMode;
+    bool mIsPrimaryClient;
 
     // stream id -> pair of (ANW* from application, OutputConfiguration used for camera service)
     std::map<int, std::pair<ANativeWindow*, OutputConfiguration>> mConfiguredOutputs;
@@ -227,7 +243,8 @@
         kWhatCaptureBufferLost, // onCaptureBufferLost
         kWhatPreparedCb, // onWindowPrepared
         // Internal cleanup
-        kWhatCleanUpSessions   // Cleanup cached sp<ACameraCaptureSession>
+        kWhatCleanUpSessions,   // Cleanup cached sp<ACameraCaptureSession>
+        kWhatClientSharedAccessPriorityChanged
     };
     static const char* kContextKey;
     static const char* kDeviceKey;
@@ -403,8 +420,8 @@
  */
 struct ACameraDevice {
     ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
-                  sp<ACameraMetadata> chars) :
-            mDevice(new android::acam::CameraDevice(id, cb, chars, this)) {}
+                  sp<ACameraMetadata> chars, bool sharedMode) :
+            mDevice(new android::acam::CameraDevice(id, cb, chars, this, sharedMode)) {}
 
     ~ACameraDevice();
 
@@ -445,7 +462,19 @@
         mDevice->setRemoteDevice(remote);
     }
 
-  private:
+    inline void setPrimaryClient(bool isPrimary) {
+        mDevice->setPrimaryClient(isPrimary);
+    }
+
+    inline bool isPrimaryClient() const {
+        return mDevice->isPrimaryClient();
+    }
+
+    inline bool isSharedMode() const{
+        return mDevice->isSharedMode();
+    }
+
+ private:
     android::sp<android::acam::CameraDevice> mDevice;
 };
 
diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc
index 1fc5352..7e70d39 100644
--- a/camera/ndk/impl/ACameraDevice.inc
+++ b/camera/ndk/impl/ACameraDevice.inc
@@ -126,5 +126,102 @@
     return ACAMERA_OK;
 }
 
+template<class T>
+camera_status_t CameraDevice::startStreamingLocked(ACameraCaptureSession* session,
+        /*optional*/T* callbacks, int numOutputWindows,
+        ANativeWindow** windows, /*optional*/int* captureSequenceId) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: camera is in closed or error state %d", __FUNCTION__, ret);
+        return ret;
+    }
+    CameraMetadata rawPreviewRequest;
+    binder::Status remoteRet = mRemote->createDefaultRequest(TEMPLATE_PREVIEW, &rawPreviewRequest);
+    if (!remoteRet.isOk()) {
+        ALOGE("%s: Create capture request failed: %s", __FUNCTION__, remoteRet.toString8().c_str());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    // ToDo: Check if the memory allocation can be freed automatically using either default_delete
+    // or ScopedAResource.
+    mPreviewRequest = new ACaptureRequest();
+    mPreviewRequest->settings = new ACameraMetadata(rawPreviewRequest.release(),
+            ACameraMetadata::ACM_REQUEST);
+    mPreviewRequest->targets  = new ACameraOutputTargets();
+    for (int i = 0; i < numOutputWindows ; i++) {
+        ACameraOutputTarget* outputTarget = nullptr;
+        ret = ACameraOutputTarget_create(windows[i], &outputTarget);
+        if (ret != ACAMERA_OK) {
+            ALOGE("%s: error while ACameraOutputTarget_create %d", __FUNCTION__, ret);
+            return ret;
+        }
+        ret = ACaptureRequest_addTarget(mPreviewRequest, outputTarget);
+        if (ret != ACAMERA_OK) {
+            ALOGE("%s: error while ACaptureRequest_addTarget %d", __FUNCTION__, ret);
+            return ret;
+        }
+        mPreviewRequestOutputs.push_back(outputTarget);
+    }
+
+    sp<CaptureRequest> req;
+    ret = allocateCaptureRequest(mPreviewRequest, req);
+    if (ret != ACAMERA_OK) {
+        ALOGE("Convert capture request to internal format failure! ret %d", ret);
+        return ret;
+    }
+    if (req->mSurfaceList.empty()) {
+        ALOGE("Capture request without output target cannot be submitted!");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+
+    // In shared session mode, if there are other active clients streaming then
+    // stoprepeating does not actually send request to HAL to cancel the request.
+    // Cameraservice will use this call to remove this client surfaces provided in its
+    // previous streaming request. If this is the only client for the shared camera device
+    // then camerservice will ask HAL to cancel the previous repeating request.
+    ret = stopRepeatingLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    hardware::camera2::utils::SubmitInfo info;
+    std::vector<int> streamIds(req->mStreamIdxList.begin(), req->mStreamIdxList.end());
+    std::vector<int> surfaceIds(req->mSurfaceIdxList.begin(), req->mSurfaceIdxList.end());
+    remoteRet = mRemote->startStreaming(streamIds, surfaceIds, &info);
+    int sequenceId = info.mRequestId;
+    int64_t lastFrameNumber = info.mLastFrameNumber;
+    if (sequenceId < 0) {
+        ALOGE("Camera %s start streaming remote failure: ret %d", getId(), sequenceId);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+
+    Vector<sp<CaptureRequest> > requestsV;
+    requestsV.push_back(req);
+    CallbackHolder cbHolder(session, requestsV, true, callbacks);
+    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+    // stopRepeating above should have cleanup repeating sequence id
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+        return ACAMERA_ERROR_CAMERA_DEVICE;
+    }
+    mRepeatingSequenceId = sequenceId;
+
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+        postSessionMsgAndCleanup(msg);
+    }
+    mIdle = false;
+    mBusySession = session;
+
+    if (captureSequenceId) {
+        *captureSequenceId = sequenceId;
+    }
+    return ACAMERA_OK;
+}
+
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 6d29ef5..07d7c21 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -28,9 +28,11 @@
 #include <memory>
 #include "ACameraDevice.h"
 #include "ACameraMetadata.h"
+#include <com_android_internal_camera_flags.h>
 
 using namespace android::acam;
 namespace vd_flags = android::companion::virtualdevice::flags;
+namespace flags = com::android::internal::camera::flags;
 
 namespace android {
 namespace acam {
@@ -838,10 +840,36 @@
 }
 
 camera_status_t
-ACameraManager::openCamera(
+ACameraManager::isCameraDeviceSharingSupported(
         const char* cameraId,
+        /*out*/bool* isSharingSupported) {
+    sp<ACameraMetadata> spChars;
+    camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+                __FUNCTION__, cameraId, ret);
+        return ret;
+    }
+
+    ACameraMetadata* chars = spChars.get();
+    ACameraMetadata_const_entry entry;
+    ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
+            &entry);
+    if (ret != ACAMERA_OK) {
+        // If shared session metadata is not found return with sharing
+        // supported as false.
+        *isSharingSupported = false;
+        return ACAMERA_OK;
+    }
+    *isSharingSupported =  (entry.count > 0) ? true : false;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+        const char* cameraId, bool sharedMode,
         ACameraDevice_StateCallbacks* callback,
-        /*out*/ACameraDevice** outDevice) {
+        /*out*/ACameraDevice** outDevice, /*out*/bool* primaryClient) {
     sp<ACameraMetadata> chars;
     camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
     Mutex::Autolock _l(mLock);
@@ -851,7 +879,7 @@
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
 
-    ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
+    ACameraDevice* device = new ACameraDevice(cameraId, callback, chars, sharedMode);
 
     sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
     if (cs == nullptr) {
@@ -876,7 +904,7 @@
     binder::Status serviceRet = cs->connectDevice(
             callbacks, cameraId, /*oomScoreOffset*/0,
             targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-            clientAttribution, static_cast<int32_t>(mDeviceContext.policy),
+            clientAttribution, static_cast<int32_t>(mDeviceContext.policy), sharedMode,
             /*out*/&deviceRemote);
 
     if (!serviceRet.isOk()) {
@@ -920,6 +948,14 @@
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
     device->setRemoteDevice(deviceRemote);
+    if (sharedMode) {
+        binder::Status remoteRet = deviceRemote->isPrimaryClient(primaryClient);
+        if (!remoteRet.isOk()) {
+            delete device;
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        device->setPrimaryClient(*primaryClient);
+    }
     *outDevice = device;
     return ACAMERA_OK;
 }
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index f4124ef..499f982 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -136,6 +136,10 @@
         virtual binder::Status onCameraOpened(const std::string&, const std::string&, int32_t) {
             return binder::Status::ok();
         }
+        virtual binder::Status onCameraOpenedInSharedMode(const std::string&, const std::string&,
+                int32_t, bool)  {
+            return binder::Status::ok();
+        }
         virtual binder::Status onCameraClosed(const std::string&, int32_t) {
             return binder::Status::ok();
         }
@@ -325,16 +329,17 @@
 
     camera_status_t getCameraCharacteristics(
             const char* cameraId, android::sp<ACameraMetadata>* characteristics);
-    camera_status_t openCamera(const char* cameraId,
+    camera_status_t openCamera(const char* cameraId, bool sharedMode,
                                ACameraDevice_StateCallbacks* callback,
-                               /*out*/ACameraDevice** device);
+                               /*out*/ACameraDevice** device, /*out*/bool* primaryClient);
     void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
     void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
     void registerExtendedAvailabilityCallback(
             const ACameraManager_ExtendedAvailabilityCallbacks* callback);
     void unregisterExtendedAvailabilityCallback(
             const ACameraManager_ExtendedAvailabilityCallbacks* callback);
-
+    camera_status_t isCameraDeviceSharingSupported(
+            const char* cameraId, bool* isSharingSupported);
   private:
     enum {
         kCameraIdListNotInit = -1
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 1400121..c2aae1c 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -1099,6 +1099,150 @@
 camera_status_t ACameraCaptureSession_prepareWindow(
     ACameraCaptureSession* session,
     ANativeWindow *window) __INTRODUCED_IN(34);
+
+/**
+ * Request continuous streaming of a sequence of images for the shared capture session
+ * when more than one clients can open the same camera in shared mode by calling
+ * {@link ACameraManager_openSharedCamera}. In shared mode, the highest priority client among all
+ * the clients will be the primary client while the others would be secondary clients. In shared
+ * capture session, only primary clients can create a capture request and change capture parameters.
+ * Secondary clients can only request streaming of images by calling this api
+ * {@link ACameraCaptureSessionShared_startStreaming}. Calling this api for normal sessions when
+ * {@link ACameraManager_openCamera} is used to open the camera will throw
+ * {@link ACAMERA_ERROR_INVALID_OPERATION}.
+ *
+ * <p>The priority of client access is determined by considering two factors: its current process
+ * state and its "out of memory" score. Clients operating in the background are assigned a lower
+ * priority. In contrast, clients running in the foreground, along with system-level clients, are
+ * given a higher priority.</p>
+ *
+ * <p>With this method, the camera device will continually capture images, cycling through the
+ * settings in the list of {@link ACaptureRequest} specified by the primary client. If primary
+ * client does not have ongoing repeating request, camera service will use a capture request with
+ * default capture parameters for preview template.</p>
+ *
+ * <p>To stop the continuous streaming, call {@link ACameraCaptureSessionShared_stopStreaming}.</p>
+ *
+ * <p>Calling this method will replace an existing continuous streaming request.</p>
+ *
+ * @param sharedSession the shared capture session when camera is opened in
+ *        shared mode.
+ * @param callbacks the {@link ACameraCaptureSession_captureCallbacks} to be associated with this
+ *        capture sequence. No capture callback will be fired if callbacks is set to NULL.
+ * @param numOutputWindows number of native windows to be used for streaming. Must be at least 1.
+ * @param windows an array of {@link ANativeWindow} to be used for streaming. Length must be at
+ *        least numOutputWindows.
+ * @param captureSequenceId the capture sequence ID associated with this capture method invocation
+ *        will be stored here if this argument is not NULL and the method call succeeds.
+ *        When this argument is set to NULL, the capture sequence ID will not be returned.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or requests is NULL, or
+ *             if numRequests < 1</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error
+ *         </li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if the session passed is not a shared
+ *              session</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for  some other reasons</li>
+ *         </ul>
+ */
+camera_status_t ACameraCaptureSessionShared_startStreaming(
+    ACameraCaptureSession* sharedSession,
+    /*optional*/ACameraCaptureSession_captureCallbacksV2 *callbacks,
+    int numOutputWindows, ANativeWindow **window,
+    /*optional*/int *captureSequenceId) __INTRODUCED_IN(36);
+
+/**
+ * This has the same functionality as ACameraCaptureSessionShared_startStreaming, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ *
+ * Request continuous streaming of a sequence of images for the shared capture session
+ * when more than one clients can open the same camera in shared mode by calling
+ * {@link ACameraManager_openSharedCamera}. In shared mode, the highest priority client among all
+ * the clients will be the primary client while the others would be secondary clients. In shared
+ * capture session, only primary clients can create a capture request and change capture parameters.
+ * Secondary clients can only request streaming of images by calling this api
+ * {@link ACameraCaptureSessionShared_logicalCamera_startStreaming}. Calling this api for normal
+ * sessions when {@link ACameraManager_openCamera} is used to open the camera will throw
+ * {@link ACAMERA_ERROR_INVALID_OPERATION}.
+ *
+ * <p>The priority of client access is determined by considering two factors: its current process
+ * state and its "out of memory" score. Clients operating in the background are assigned a lower
+ * priority. In contrast, clients running in the foreground, along with system-level clients, are
+ * given a higher priority.</p>
+ *
+ * <p>With this method, the camera device will continually capture images, cycling through the
+ * settings in the list of {@link ACaptureRequest} specified by the primary client. If primary
+ * client does not have ongoing repeating request, camera service will use a capture request with
+ * default capture parameters for preview template.</p>
+ *
+ * <p>To stop the continuous streaming, call {@link ACameraCaptureSessionShared_stopStreaming}.</p>
+ *
+ * <p>Calling this method will replace an existing continuous streaming request.</p>
+ *
+ * @param sharedSession the shared capture session when camera is opened in
+ *        shared mode.
+ * @param callbacks the {@link ACameraCaptureSession_logicalCamera_captureCallbacksV2} to be
+ *        associated with this capture sequence. No capture callback will be fired if callbacks
+ *        is set to NULL.
+ * @param numOutputWindows number of native windows to be used for streaming. Must be at least 1.
+ * @param windows an array of {@link ANativeWindow} to be used for streaming. Length must be at
+ *        least numOutputWindows.
+ * @param captureSequenceId the capture sequence ID associated with this capture method invocation
+ *        will be stored here if this argument is not NULL and the method call succeeds.
+ *        When this argument is set to NULL, the capture sequence ID will not be returned.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ *             if it is not NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or requests is NULL, or
+ *             if numRequests < 1</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error
+ *         </li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if the session passed is not a shared
+ *              session</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for  some other reasons</li>
+ *         </ul>
+ */
+camera_status_t ACameraCaptureSessionShared_logicalCamera_startStreaming(
+    ACameraCaptureSession* sharedSession,
+    /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2 *callbacks,
+    int numOutputWindows, ANativeWindow **windows,
+    /*optional*/int *captureSequenceId) __INTRODUCED_IN(36);
+
+/**
+ * Cancel any ongoing streaming started by {@link ACameraCaptureSessionShared_startStreaming}.
+ * Calling this api does not effect any streaming requests submitted by other clients who have
+ * opened the camera in shared mode. Calling this api for normal sessions when
+ * {@link ACameraManager_openCamera} is used to open the camera will throw
+ * {@link ACAMERA_ERROR_INVALID_OPERATION}.
+ *
+ * @param sharedSession the capture session of interest
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session is NULL.</li>
+ *         <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error
+ *         </li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if the session passed is not a shared
+ *              session</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li>
+ *         </ul>
+ */
+camera_status_t ACameraCaptureSessionShared_stopStreaming(
+    ACameraCaptureSession* sharedSession)  __INTRODUCED_IN(36);
 __END_DECLS
 
 #endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index fbd0ee1..8c7eb1f 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -125,6 +125,18 @@
 typedef void (*ACameraDevice_ErrorStateCallback)(void* context, ACameraDevice* device, int error);
 
 /**
+ * Client access priorities changed callbacks to be used in {@link ACameraDevice_StateCallbacks}
+ * when camera is opened in shared mode.
+ *
+ * @param context The optional context in {@link ACameraDevice_StateCallbacks} will be passed to
+ *                this callback.
+ * @param device The {@link ACameraDevice} whose access priorities has been changed.
+ * @param isPrimaryClient whether the client is primary client.
+ */
+typedef void (*ACameraDevice_ClientSharedAccessPriorityChangedCallback)(void* context,
+        ACameraDevice* device, bool isPrimaryClient);
+
+/**
  * Applications' callbacks for camera device state changes, register with
  * {@link ACameraManager_openCamera}.
  */
@@ -163,6 +175,17 @@
      *
      */
     ACameraDevice_ErrorStateCallback  onError;
+
+    /**
+     * Notify registered clients about client shared access priority changes when the camera device
+     * has been opened in shared mode.
+     *
+     * If the client priority changes from secondary to primary, then it can now
+     * create capture request and change the capture request parameters. If client priority
+     * changes from primary to secondary, that implies that another higher priority client is also
+     * accessing the camera in shared mode and is now the primary client.
+     */
+    ACameraDevice_ClientSharedAccessPriorityChangedCallback onClientSharedAccessPriorityChanged;
 } ACameraDevice_StateCallbacks;
 
 /**
@@ -671,7 +694,9 @@
  *         <li>{@link ACAMERA_OK} if the method call succeeds. The created capture session will be
  *                                filled in session argument.</li>
  *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if any of device, outputs, callbacks or
- *                                session is NULL.</li>
+ *                                session is NULL or if the outputs does not match the predefined
+ *                                shared session configuration when camera is opened in shared mode.
+ *                                </li>
  *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.</li>
  *         <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.</li>
  *         <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.</li>
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index b4f3bf1..492c41b 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -293,6 +293,61 @@
         /*out*/ACameraDevice** device) __INTRODUCED_IN(24);
 
 /**
+ * Open a shared connection to a camera with the given ID. The opened camera device will be
+ * returned in the `device` parameter. The behavior of this method matches that of
+ * {@link ACameraManager_openCamera(ACameraManager*, const char*, ACameraDevice_StateCallbacks*,
+ * ACameraDevice**)} except that it opens the camera in shared mode so that more
+ * than one client can access the camera at the same time.
+ *
+ * <p>When camera is opened in shared mode, the highest priority client among all the clients will
+ * be the primary client while the others would be secondary clients. Primary clients can create
+ * capture requests, modify any capture parameters and send them to the capture session for a
+ * one-shot capture or as a repeating request.</p>
+ *
+ * <p>Secondary clients cannot create a capture request and modify any capture parameters. However,
+ * they can start the camera streaming to desired surface targets using
+ * {@link ACameraCaptureSessionShared_startStreaming}. Once the streaming has successfully started,
+ * then they can stop the streaming using {@link ACameraCaptureSessionShared_stopStreaming}.</p>
+ *
+ * <p>The priority of client access is determined by considering two factors: its current process
+ * state and its "out of memory" score. Clients operating in the background are assigned a lower
+ * priority. In contrast, clients running in the foreground, along with system-level clients, are
+ * given a higher priority.</p>
+ *
+ * <p>Processes need to have android.permission.SYSTEM_CAMERA in addition to
+ * android.permission.CAMERA in order to connect to this camera device in shared
+ * mode.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device to be opened.
+ * @param callback the {@link ACameraDevice_StateCallbacks} associated with the opened camera
+ *                 device.
+ * @param device the opened {@link ACameraDevice} will be filled here if the method call succeeds.
+ * @param isPrimaryClient will return as true if the client is a primary client.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager, cameraId, callback, or device
+ *                  is NULL, or cameraId does not match any camera devices connected.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if connection to camera service fails.</li>
+ *         <li>{@link ACAMERA_ERROR_NOT_ENOUGH_MEMORY} if allocating memory fails.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_IN_USE} if camera device is being used by a higher
+ *                   priority camera API client.</li>
+ *         <li>{@link ACAMERA_ERROR_MAX_CAMERA_IN_USE} if the system-wide limit for number of open
+ *                   cameras or camera resources has been reached, and more camera devices cannot be
+ *                   opened until previous instances are closed.</li>
+ *         <li>{@link ACAMERA_ERROR_CAMERA_DISABLED} if the camera is disabled due to a device
+ *                   policy, and cannot be opened.</li>
+ *         <li>{@link ACAMERA_ERROR_PERMISSION_DENIED} if the application does not have permission
+ *                   to open camera.</li>
+ *         <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraManager_openSharedCamera(
+        ACameraManager* manager, const char* cameraId,
+        ACameraDevice_StateCallbacks* callback,
+        /*out*/ACameraDevice** device,/*out*/bool* isPrimaryClient) __INTRODUCED_IN(36);
+
+/**
  * Definition of camera access permission change callback.
  *
  * <p>Notification that camera access priorities have changed and the camera may
@@ -397,6 +452,27 @@
         ACameraManager* manager,
         const ACameraManager_ExtendedAvailabilityCallbacks* callback) __INTRODUCED_IN(29);
 
+
+/**
+ * Checks if a camera can be opened in shared mode by multiple clients.
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device of interest.
+ * @param isSharingSupported output will be filled here if the method succeeds.
+ *        This will be true if camera can be opened in shared mode, false
+ *        otherwise.
+ *
+ * @return <ul>
+ *         <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ *         <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager, cameraId, or isSharingSupported
+ *                  is NULL, or cameraId does not match any camera devices connected.</li>
+ *         </ul>
+ */
+camera_status_t ACameraManager_isCameraDeviceSharingSupported(
+        ACameraManager *manager,
+        const char *cameraId,
+        bool *isSharingSupported) __INTRODUCED_IN(36);
+
 #ifdef __ANDROID_VNDK__
 /**
  * Retrieve the tag value, given the tag name and camera id.
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1817490..c713077 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -91,6 +91,7 @@
     ACAMERA_AUTOMOTIVE_LENS,
     ACAMERA_EXTENSION,
     ACAMERA_JPEGR,
+    ACAMERA_SHARED_SESSION,
     ACAMERA_SECTION_COUNT,
 
     ACAMERA_VENDOR = 0x8000
@@ -138,6 +139,7 @@
     ACAMERA_AUTOMOTIVE_LENS_START  = ACAMERA_AUTOMOTIVE_LENS   << 16,
     ACAMERA_EXTENSION_START        = ACAMERA_EXTENSION         << 16,
     ACAMERA_JPEGR_START            = ACAMERA_JPEGR             << 16,
+    ACAMERA_SHARED_SESSION_START   = ACAMERA_SHARED_SESSION    << 16,
     ACAMERA_VENDOR_START           = ACAMERA_VENDOR            << 16
 } acamera_metadata_section_start_t;
 
@@ -11571,6 +11573,7 @@
 
 
 
+
 __END_DECLS
 
 #endif /* _NDK_CAMERA_METADATA_TAGS_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 7d7868b..60d4775 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -28,6 +28,8 @@
     ACameraManager_getCameraCharacteristics;
     ACameraManager_getCameraIdList;
     ACameraManager_openCamera;
+    ACameraManager_openSharedCamera; # systemapi introduced=36
+    ACameraManager_isCameraDeviceSharingSupported; # systemapi introduced=36
     ACameraManager_registerAvailabilityCallback;
     ACameraManager_unregisterAvailabilityCallback;
     ACameraManager_registerExtendedAvailabilityCallback; # introduced=29
@@ -72,6 +74,9 @@
     ACaptureSessionSharedOutput_remove; # introduced=28
     ACaptureSessionPhysicalOutput_create; # introduced=29
     ACaptureSessionOutput_free;
+    ACameraCaptureSessionShared_startStreaming; # systemapi introduced=36
+    ACameraCaptureSessionShared_logicalCamera_startStreaming; # systemapi introduced=36
+    ACameraCaptureSessionShared_stopStreaming; # systemapi introduced=36
   local:
     *;
 };
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 3325da6..2c32636 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -85,11 +85,12 @@
         const char* id,
         ACameraDevice_StateCallbacks* cb,
         sp<ACameraMetadata> chars,
-        ACameraDevice* wrapper) :
+        ACameraDevice* wrapper, bool sharedMode) :
         mCameraId(id),
         mAppCallbacks(*cb),
         mChars(std::move(chars)),
         mWrapper(wrapper),
+        mSharedMode(sharedMode),
         mInError(false),
         mError(ACAMERA_OK),
         mIdle(true),
@@ -561,6 +562,28 @@
     return ACAMERA_OK;
 }
 
+camera_status_t CameraDevice::stopStreamingLocked() {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: camera is in closed or error state %d", __FUNCTION__, ret);
+        return ret;
+    }
+    ret = stopRepeatingLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: error when trying to stop streaming %d", __FUNCTION__, ret);
+        return ret;
+    }
+    for (auto& outputTarget : mPreviewRequestOutputs) {
+        ACameraOutputTarget_free(outputTarget);
+    }
+    mPreviewRequestOutputs.clear();
+    if (mPreviewRequest) {
+        ACaptureRequest_free(mPreviewRequest);
+        mPreviewRequest = nullptr;
+    }
+    return ACAMERA_OK;
+}
+
 camera_status_t CameraDevice::flushLocked(ACameraCaptureSession* session) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
@@ -960,6 +983,7 @@
         case kWhatCaptureSeqAbort:
         case kWhatCaptureBufferLost:
         case kWhatPreparedCb:
+        case kWhatClientSharedAccessPriorityChanged:
             ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
             break;
         case kWhatCleanUpSessions:
@@ -997,6 +1021,28 @@
             (*onDisconnected)(context, dev);
             break;
         }
+        case kWhatClientSharedAccessPriorityChanged:
+        {
+            ACameraDevice* dev;
+            found = msg->findPointer(kDeviceKey, (void**) &dev);
+            if (!found || dev == nullptr) {
+                ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+                return;
+            }
+            ACameraDevice_ClientSharedAccessPriorityChangedCallback
+                    onClientSharedAccessPriorityChanged;
+            found = msg->findPointer(kCallbackFpKey, (void**) &onClientSharedAccessPriorityChanged);
+            if (!found) {
+                ALOGE("%s: Cannot find onClientSharedAccessPriorityChanged!", __FUNCTION__);
+                return;
+            }
+            if (onClientSharedAccessPriorityChanged == nullptr) {
+                return;
+            }
+            (*onClientSharedAccessPriorityChanged)(context, dev, dev->isPrimaryClient());
+            break;
+        }
+
         case kWhatOnError:
         {
             ACameraDevice* dev;
@@ -1614,6 +1660,28 @@
     return ScopedAStatus::ok();
 }
 
+ScopedAStatus CameraDevice::ServiceCallback::onClientSharedAccessPriorityChanged(
+        bool primaryClient) {
+    ALOGV("onClientSharedAccessPriorityChanged received. primaryClient = %d", primaryClient);
+    ScopedAStatus ret = ScopedAStatus::ok();
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
+    if (dev == nullptr) {
+        return ret; // device has been closed
+    }
+    Mutex::Autolock _l(dev->mDeviceLock);
+    if (dev->isClosed() || dev->mRemote == nullptr) {
+        return ret;
+    }
+    dev->setPrimaryClient(primaryClient);
+    sp<AMessage> msg = new AMessage(kWhatClientSharedAccessPriorityChanged, dev->mHandler);
+    msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+    msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+    msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onClientSharedAccessPriorityChanged);
+    msg->post();
+
+    return ScopedAStatus::ok();
+}
+
 ScopedAStatus CameraDevice::ServiceCallback::onDeviceIdle() {
     ALOGV("Camera is now idle");
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index b771d47..5d03e95 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -95,7 +95,7 @@
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
                   sp<ACameraMetadata> chars,
-                  ACameraDevice* wrapper);
+                  ACameraDevice* wrapper, bool sharedMode);
     ~CameraDevice();
 
     // Called to initialize fields that require shared_ptr to `this`
@@ -136,6 +136,7 @@
                                             const CaptureResultExtras& in_resultExtras,
                                             const std::vector<PhysicalCaptureResultInfo>&
                                                     in_physicalCaptureResultInfos) override;
+         ndk::ScopedAStatus onClientSharedAccessPriorityChanged(bool isPrimaryClient) override;
 
       private:
         camera_status_t readOneResultMetadata(const CaptureMetadataInfo& captureMetadataInfo,
@@ -154,6 +155,9 @@
 
     // Stop the looper thread and unregister the handler
     void stopLooperAndDisconnect();
+    void setPrimaryClient(bool isPrimary) {mIsPrimaryClient = isPrimary;};
+    bool isPrimaryClient() {return mIsPrimaryClient;};
+    bool isSharedMode() {return mSharedMode;};
 
   private:
     friend ACameraCaptureSession;
@@ -192,6 +196,13 @@
             /*out*/int* captureSequenceId,
             bool isRepeating);
 
+    camera_status_t stopStreamingLocked();
+
+    template<class T>
+    camera_status_t startStreamingLocked(ACameraCaptureSession* session,
+            /*optional*/T* callbacks,
+            int numOutputWindows, ANativeWindow** windows, /*optional*/int* captureSequenceId);
+
     void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp<CaptureRequest> &req);
 
     camera_status_t updateOutputConfigurationLocked(ACaptureSessionOutput *output);
@@ -232,6 +243,10 @@
     const sp<ACameraMetadata> mChars;    // Camera characteristics
     std::shared_ptr<ServiceCallback> mServiceCallback;
     ACameraDevice* mWrapper;
+    bool mSharedMode;
+    bool mIsPrimaryClient;
+    ACaptureRequest* mPreviewRequest = nullptr;
+    std::vector<ACameraOutputTarget*> mPreviewRequestOutputs;
 
     // stream id -> pair of (ACameraWindowType* from application, OutputConfiguration used for
     // camera service)
@@ -274,7 +289,8 @@
         kWhatCaptureBufferLost, // onCaptureBufferLost
         kWhatPreparedCb, // onPrepared
         // Internal cleanup
-        kWhatCleanUpSessions   // Cleanup cached sp<ACameraCaptureSession>
+        kWhatCleanUpSessions,   // Cleanup cached sp<ACameraCaptureSession>
+        kWhatClientSharedAccessPriorityChanged
     };
     static const char* kContextKey;
     static const char* kDeviceKey;
@@ -434,9 +450,9 @@
  */
 struct ACameraDevice {
     ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
-                  sp<ACameraMetadata> chars) :
+                  sp<ACameraMetadata> chars, bool sharedMode) :
             mDevice(std::make_shared<android::acam::CameraDevice>(id, cb,
-                                                                std::move(chars), this)) {
+            std::move(chars), this, sharedMode)) {
         mDevice->init();
     }
 
@@ -481,6 +497,16 @@
     inline bool setDeviceMetadataQueues() {
         return mDevice->setDeviceMetadataQueues();
     }
+    inline void setPrimaryClient(bool isPrimary) {
+        mDevice->setPrimaryClient(isPrimary);
+    }
+    inline bool isPrimaryClient() const {
+        return mDevice->isPrimaryClient();
+    }
+    inline bool isSharedMode() const {
+        return mDevice->isSharedMode();
+    }
+
   private:
     std::shared_ptr<android::acam::CameraDevice> mDevice;
 };
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
index 1e724eb..1f568d2 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -147,5 +147,131 @@
     return ACAMERA_OK;
 }
 
+template<class T>
+camera_status_t CameraDevice::startStreamingLocked(ACameraCaptureSession* session,
+        /*optional*/T* callbacks, int numOutputWindows,
+        ANativeWindow** windows, /*optional*/int* captureSequenceId) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: camera is in closed or error state %d", __FUNCTION__, ret);
+        return ret;
+    }
+    utils::AidlCameraMetadata aidlMetadata;
+    ndk::ScopedAStatus remoteRet = mRemote->createDefaultRequest(utils::TemplateId::PREVIEW,
+            &aidlMetadata);
+    if (!remoteRet.isOk()) {
+        if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+            ALOGE("%s: submitRequestList call failed: %s",
+                  __FUNCTION__, toString(errStatus).c_str());
+            return utils::convertFromAidl(errStatus);
+        } else {
+            ALOGE("%s: Transaction error for submitRequestList call: %d", __FUNCTION__,
+                  remoteRet.getExceptionCode());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+    }
+    camera_metadata_t* rawPreviewRequest;
+    utils::cloneFromAidl(aidlMetadata, &rawPreviewRequest);
+    // ToDo: Check if the memory allocation can be freed automatically using either default_delete
+    // or ScopedAResource.
+    mPreviewRequest = new ACaptureRequest();
+    mPreviewRequest->settings = new ACameraMetadata(rawPreviewRequest,
+            ACameraMetadata::ACM_REQUEST);
+    mPreviewRequest->targets  = new ACameraOutputTargets();
+    for (int i = 0; i < numOutputWindows ; i++) {
+        ACameraOutputTarget* outputTarget = nullptr;
+        ret = ACameraOutputTarget_create(windows[i], &outputTarget);
+        if (ret != ACAMERA_OK) {
+            ALOGE("%s: error while ACameraOutputTarget_create %d", __FUNCTION__, ret);
+            return ret;
+        }
+        ret = ACaptureRequest_addTarget(mPreviewRequest, outputTarget);
+        if (ret != ACAMERA_OK) {
+            ALOGE("%s: error while ACaptureRequest_addTarget %d", __FUNCTION__, ret);
+            return ret;
+        }
+        mPreviewRequestOutputs.push_back(outputTarget);
+    }
+
+    std::vector<sp<CaptureRequest>> requestsV;
+    sp<CaptureRequest> req;
+    ret = allocateCaptureRequestLocked(mPreviewRequest, req);
+    // We need to call this method since after submitRequestList is called,
+    // the request metadata queue might have removed the capture request
+    // metadata. Therefore we simply add the metadata to its wrapper class,
+    // so that it can be retrieved later.
+    addRequestSettingsMetadata(mPreviewRequest, req);
+    if (ret != ACAMERA_OK) {
+        ALOGE("Convert capture request to internal format failure! ret %d", ret);
+        return ret;
+    }
+    if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
+        ALOGE("Capture request without output target cannot be submitted!");
+        return ACAMERA_ERROR_INVALID_PARAMETER;
+    }
+    requestsV.push_back(req);
+    // In shared session mode, if there are other active clients streaming then
+    // stoprepeating does not actually send request to HAL to cancel the request.
+    // Cameraservice will use this call to remove this client surfaces provided in its
+    // previous streaming request. If this is the only client for the shared camera device
+    // then camerservice will ask HAL to cancel the previous repeating request.
+    ret = stopRepeatingLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+        return ret;
+    }
+    SubmitInfo info;
+    std::vector<int> streamIds;
+    std::vector<int> surfaceIds;
+    for (const auto& streamAndWindowId : req->mCaptureRequest.streamAndWindowIds) {
+        streamIds.push_back(streamAndWindowId.streamId);
+        surfaceIds.push_back(streamAndWindowId.windowId);
+    }
+    remoteRet = mRemote->startStreaming(streamIds, surfaceIds, &info);
+    if (!remoteRet.isOk()) {
+        if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+            ALOGE("%s: startStreaming call failed: %s",
+                  __FUNCTION__, toString(errStatus).c_str());
+            return utils::convertFromAidl(errStatus);
+        } else {
+            ALOGE("%s: Transaction error for startStreaming call: %d", __FUNCTION__,
+                  remoteRet.getExceptionCode());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+    }
+
+    int32_t sequenceId = info.requestId;
+    int64_t lastFrameNumber = info.lastFrameNumber;
+    if (sequenceId < 0) {
+        ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    CallbackHolder cbHolder(session, requestsV, true, callbacks);
+    mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+    // stopRepeating above should have cleanup repeating sequence id
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+        return ACAMERA_ERROR_CAMERA_DEVICE;
+    }
+    mRepeatingSequenceId = sequenceId;
+
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+        postSessionMsgAndCleanup(msg);
+    }
+    mIdle = false;
+    mBusySession = session;
+
+    if (captureSequenceId) {
+        *captureSequenceId = sequenceId;
+    }
+    return ACAMERA_OK;
+}
+
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index cdba8ff..b59964c 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -791,10 +791,33 @@
 }
 
 camera_status_t
-ACameraManager::openCamera(
+ACameraManager::isCameraDeviceSharingSupported(
         const char* cameraId,
+        /*out*/bool* isSharingSupported) {
+    sp<ACameraMetadata> spChars;
+    camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
+    if (ret != ACAMERA_OK) {
+        ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+                __FUNCTION__, cameraId, ret);
+        return ret;
+    }
+
+    ACameraMetadata* chars = spChars.get();
+    ACameraMetadata_const_entry entry;
+    ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
+            &entry);
+    if (ret != ACAMERA_OK) {
+        return ret;
+    }
+    *isSharingSupported =  (entry.count > 0) ? true : false;
+    return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+        const char* cameraId, bool sharedMode,
         ACameraDevice_StateCallbacks* callback,
-        /*out*/ACameraDevice** outDevice) {
+        /*out*/ACameraDevice** outDevice, /*out*/bool* isPrimaryClient) {
     sp<ACameraMetadata> rawChars;
     camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
     Mutex::Autolock _l(mLock);
@@ -804,7 +827,7 @@
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
 
-    ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars));
+    ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars), sharedMode);
 
     std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
     if (cs == nullptr) {
@@ -815,11 +838,18 @@
 
     std::shared_ptr<BnCameraDeviceCallback> deviceCallback = device->getServiceCallback();
     std::shared_ptr<ICameraDeviceUser> deviceRemote;
+    ScopedAStatus serviceRet;
 
     // No way to get package name from native.
     // Send a zero length package name and let camera service figure it out from UID
-    ScopedAStatus serviceRet = cs->connectDevice(deviceCallback,
-                                                 std::string(cameraId), &deviceRemote);
+    if (sharedMode) {
+        serviceRet = cs->connectDeviceV2(deviceCallback,
+                std::string(cameraId), sharedMode, &deviceRemote);
+    } else {
+        serviceRet = cs->connectDevice(deviceCallback,
+                std::string(cameraId), &deviceRemote);
+    }
+
     if (!serviceRet.isOk()) {
         if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
             Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
@@ -842,6 +872,13 @@
     }
 
     device->setRemoteDevice(deviceRemote);
+    if (sharedMode) {
+        ScopedAStatus remoteRet = deviceRemote->isPrimaryClient(isPrimaryClient);
+        if (!remoteRet.isOk()) {
+            return ACAMERA_ERROR_UNKNOWN;
+        }
+        device->setPrimaryClient(*isPrimaryClient);
+    }
     device->setDeviceMetadataQueues();
     *outDevice = device;
     return ACAMERA_OK;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 2d8eefa..2fa4cce 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -261,9 +261,9 @@
     camera_status_t getCameraCharacteristics(
             const char* cameraId, android::sp<ACameraMetadata>* characteristics);
 
-    camera_status_t openCamera(const char* cameraId,
-                               ACameraDevice_StateCallbacks* callback,
-                               /*out*/ACameraDevice** device);
+    camera_status_t openCamera(const char* cameraId, bool sharedMode,
+            ACameraDevice_StateCallbacks* callback, /*out*/ACameraDevice** device,
+            /*out*/bool* primaryClient);
     camera_status_t getTagFromName(const char *cameraId, const char *name, uint32_t *tag);
     void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
     void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
@@ -271,6 +271,8 @@
             const ACameraManager_ExtendedAvailabilityCallbacks* callback);
     void unregisterExtendedAvailabilityCallback(
             const ACameraManager_ExtendedAvailabilityCallbacks* callback);
+    camera_status_t isCameraDeviceSharingSupported(const char *cameraId,
+            bool *isSharingSupported);
 
   private:
     enum {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 5135b5d..4384df9 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -130,6 +130,15 @@
         return binder::Status::ok();
     }
 
+    virtual binder::Status onCameraOpenedInSharedMode(
+            [[maybe_unused]] const std::string& /*cameraId*/,
+            [[maybe_unused]] const std::string& /*clientPackageName*/,
+            [[maybe_unused]] int32_t /*deviceId*/,
+            [[maybe_unused]] bool /*isPrimaryClient*/) override {
+        // No op
+        return binder::Status::ok();
+    }
+
     bool waitForNumCameras(size_t num) const {
         Mutex::Autolock l(mLock);
 
@@ -281,6 +290,12 @@
         return binder::Status::ok();
     }
 
+    virtual binder::Status onClientSharedAccessPriorityChanged(
+            [[maybe_unused]] bool /*isPrimaryClient*/) {
+        // No-op
+        return binder::Status::ok();
+    }
+
     // Test helper functions:
 
     bool hadError() const {
@@ -402,7 +417,8 @@
         res = service->connectDevice(callbacks, cameraId,
                 /*oomScoreOffset*/ 0,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__,
-                /*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0, /*out*/&device);
+                /*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0,
+                /*sharedMode*/false, /*out*/&device);
         EXPECT_TRUE(res.isOk()) << res;
         ASSERT_NE(nullptr, device.get());
         device->disconnect();
@@ -451,7 +467,7 @@
                     /*oomScoreOffset*/ 0,
                     /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                     /*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0,
-                    /*out*/&device);
+                    /*sharedMode*/false, /*out*/&device);
             EXPECT_TRUE(res.isOk()) << res;
         }
         auto p = std::make_pair(callbacks, device);
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
index 4ec26d6..8f5081a 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -542,6 +542,7 @@
 
     Dav1dSettings lib_settings;
     dav1d_default_settings(&lib_settings);
+    lib_settings.all_layers = 0;
     int cpu_count = GetCPUCoreCount();
     lib_settings.n_threads = std::max(cpu_count / 2, 1);  // use up to half the cores by default.
 
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index fcdaff9..e413241 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -33,6 +33,7 @@
         "liblog",
     ],
     shared_libs: [
+        "camera_platform_flags_c_lib",
         "framework-permission-aidl-cpp",
         "libbinder",
         "libbinder_ndk",
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index a74b6d6..fbc613c 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -73,6 +73,7 @@
         "libsensorprivacy",
         "libstagefright",
         "libstagefright_foundation",
+        "libtinyxml2",
         "libvendorsupport",
         "libxml2",
         "libyuv",
@@ -101,8 +102,8 @@
         "android.frameworks.cameraservice.device@2.0",
         "android.frameworks.cameraservice.device@2.1",
         "android.frameworks.cameraservice.common-V1-ndk",
-        "android.frameworks.cameraservice.service-V2-ndk",
-        "android.frameworks.cameraservice.device-V2-ndk",
+        "android.frameworks.cameraservice.service-V3-ndk",
+        "android.frameworks.cameraservice.device-V3-ndk",
         "android.hardware.camera.common-V1-ndk",
         "android.hardware.camera.device-V3-ndk",
         "android.hardware.camera.metadata-V3-ndk",
@@ -140,6 +141,8 @@
         "common/FrameProcessorBase.cpp",
         "common/hidl/HidlProviderInfo.cpp",
         "common/aidl/AidlProviderInfo.cpp",
+        "config/SharedSessionConfigUtils.cpp",
+        "config/SharedSessionConfigReader.cpp",
         "api1/Camera2Client.cpp",
         "api1/client2/Parameters.cpp",
         "api1/client2/FrameProcessor.cpp",
@@ -179,6 +182,7 @@
         "device3/aidl/AidlCamera3Device.cpp",
         "device3/aidl/AidlCamera3OutputUtils.cpp",
         "device3/aidl/AidlCamera3OfflineSession.cpp",
+        "device3/aidl/AidlCamera3SharedDevice.cpp",
         "gui/RingBufferConsumer.cpp",
         "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
@@ -218,6 +222,7 @@
         "libcamera_client",
         "libfmq",
         "libsensorprivacy",
+        "libtinyxml2",
     ],
 
     include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index eb8708e..f030b91 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -550,7 +550,7 @@
         updateStatus(StatusInternal::NOT_PRESENT, cameraId);
         mVirtualDeviceCameraIdMapper.removeCamera(cameraId);
 
-        sp<BasicClient> clientToDisconnectOnline, clientToDisconnectOffline;
+        std::vector<sp<BasicClient>> clientsToDisconnectOnline, clientsToDisconnectOffline;
         {
             // Don't do this in updateStatus to avoid deadlock over mServiceLock
             Mutex::Autolock lock(mServiceLock);
@@ -560,12 +560,12 @@
 
             // Remove online as well as offline client from the list of active clients,
             // if they are present
-            clientToDisconnectOnline = removeClientLocked(cameraId);
-            clientToDisconnectOffline = removeClientLocked(kOfflineDevice + cameraId);
+            clientsToDisconnectOnline = removeClientsLocked(cameraId);
+            clientsToDisconnectOffline = removeClientsLocked(kOfflineDevice + cameraId);
         }
 
-        disconnectClient(cameraId, clientToDisconnectOnline);
-        disconnectClient(kOfflineDevice + cameraId, clientToDisconnectOffline);
+        disconnectClients(cameraId, clientsToDisconnectOnline);
+        disconnectClients(kOfflineDevice + cameraId, clientsToDisconnectOffline);
 
         removeStates(cameraId);
     } else {
@@ -639,6 +639,13 @@
     }
 }
 
+void CameraService::disconnectClients(const std::string& id,
+        std::vector<sp<BasicClient>> clientsToDisconnect) {
+    for (auto& client : clientsToDisconnect) {
+        disconnectClient(id, client);
+    }
+}
+
 void CameraService::disconnectClient(const std::string& id, sp<BasicClient> clientToDisconnect) {
     if (clientToDisconnect.get() != nullptr) {
         ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL",
@@ -1471,7 +1478,7 @@
         int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
         int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
         apiLevel effectiveApiLevel, bool overrideForPerfClass, int rotationOverride,
-        bool forceSlowJpegMode, const std::string& originalCameraId,
+        bool forceSlowJpegMode, const std::string& originalCameraId, bool sharedMode,
         /*out*/sp<BasicClient>* client) {
     // For HIDL devices
     if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
@@ -1507,7 +1514,7 @@
                 cameraService->mAttributionAndPermissionUtils, packageName, featureId, cameraId,
                 api1CameraId, facing, sensorOrientation,
                 clientPid, clientUid, servicePid, overrideForPerfClass, rotationOverride,
-                forceSlowJpegMode);
+                forceSlowJpegMode, /*sharedMode*/false);
         ALOGI("%s: Camera1 API (legacy), rotationOverride %d, forceSlowJpegMode %d",
                 __FUNCTION__, rotationOverride, forceSlowJpegMode);
     } else { // Camera2 API route
@@ -1517,7 +1524,7 @@
                 cameraService->mCameraServiceProxyWrapper,
                 cameraService->mAttributionAndPermissionUtils, packageName, systemNativeClient,
                 featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid,
-                overrideForPerfClass, rotationOverride, originalCameraId);
+                overrideForPerfClass, rotationOverride, originalCameraId, sharedMode);
         ALOGI("%s: Camera2 API, rotationOverride %d", __FUNCTION__, rotationOverride);
     }
     return Status::ok();
@@ -1613,7 +1620,7 @@
             API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
             /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
             /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
-            /*forceSlowJpegMode*/false, cameraIdStr, /*isNonSystemNdk*/ false, /*out*/ tmp)
+            /*forceSlowJpegMode*/false, cameraIdStr, /*isNonSystemNdk*/ false, /*sharedMode*/false, /*out*/ tmp)
             ).isOk()) {
         ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().c_str());
     }
@@ -1683,14 +1690,13 @@
 }
 
 Status CameraService::validateConnectLocked(const std::string& cameraId,
-        const std::string& clientName8, int clientUid, int clientPid) const {
-
+        const std::string& clientName8, int clientUid, int clientPid, bool sharedMode) const {
 #ifdef __BRILLO__
     UNUSED(clientName8);
     UNUSED(clientUid);
     UNUSED(clientPid);
 #else
-    Status allowed = validateClientPermissionsLocked(cameraId, clientName8, clientUid, clientPid);
+    Status allowed = validateClientPermissionsLocked(cameraId, clientName8, clientUid, clientPid, sharedMode);
     if (!allowed.isOk()) {
         return allowed;
     }
@@ -1742,7 +1748,7 @@
 }
 
 Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
-        const std::string& clientName, int clientUid, int clientPid) const {
+        const std::string& clientName, int clientUid, int clientPid, bool sharedMode) const {
     int callingPid = getCallingPid();
     int callingUid = getCallingUid();
 
@@ -1759,6 +1765,14 @@
                 "found while trying to query device kind", cameraId.c_str());
     }
 
+    if (sharedMode
+            && (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA)) {
+        ALOGE("%s: camera id %s is not system camera. Device sharing only supported for"
+                " system cameras.", __FUNCTION__, cameraId.c_str());
+        return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "camera device sharing not supported for "
+                "camera ID \"%s\"", cameraId.c_str());
+    }
+
     // Get the device id that owns this camera.
     auto [deviceId, _] = mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
 
@@ -1880,6 +1894,26 @@
                 __FUNCTION__);
     }
 
+    sp<BasicClient> clientSp = clientDescriptor->getValue();
+    auto primaryClient = mActiveClientManager.getPrimaryClient(desc->getKey());
+    if (primaryClient == nullptr) {
+        // There is no primary client yet. Assign this first client as
+        // primary
+        clientSp->setPrimaryClient(true);
+    } else {
+        // There is already primary client. If the incoming client has a
+        // higher priority than the existing primary, then assign incoming
+        // client as primary and change the existing client to secondary.
+        // Otherwise incoming client is secondary client.
+        if (clientDescriptor->getPriority() <= primaryClient->getPriority()) {
+            clientSp->setPrimaryClient(true);
+            primaryClient->getValue()->setPrimaryClient(false);
+            primaryClient->getValue()->notifyClientSharedAccessPriorityChanged(false);
+        } else {
+            clientSp->setPrimaryClient(false);
+        }
+    }
+
     // And register a death notification for the client callback. Do
     // this last to avoid Binder policy where a nested Binder
     // transaction might be pre-empted to service the client death
@@ -1894,6 +1928,7 @@
 status_t CameraService::handleEvictionsLocked(const std::string& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
         const std::string& packageName, int oomScoreOffset, bool systemNativeClient,
+        bool sharedMode,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial) {
@@ -1945,7 +1980,8 @@
             clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                     sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                     state->getConflicting(), resource_policy::NATIVE_ADJ, clientPid,
-                    ActivityManager::PROCESS_STATE_BOUND_TOP, oomScoreOffset, systemNativeClient);
+                    ActivityManager::PROCESS_STATE_BOUND_TOP, oomScoreOffset, systemNativeClient,
+                    sharedMode);
         } else {
             // Get current active client PIDs
             std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
@@ -1981,7 +2017,7 @@
             clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                     sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                     state->getConflicting(), actualScore, clientPid, actualState,
-                    oomScoreOffset, systemNativeClient);
+                    oomScoreOffset, systemNativeClient, sharedMode);
         }
 
         resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
@@ -2160,7 +2196,7 @@
             clientPackageName, /*systemNativeClient*/ false, {},
             clientUid, clientPid, API_1,
             /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
-            rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);
+            rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*sharedMode*/false, /*out*/client);
 
     if (!ret.isOk()) {
         logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or(""),
@@ -2243,8 +2279,7 @@
         const std::string& unresolvedCameraId,
         int oomScoreOffset, int targetSdkVersion,
         int rotationOverride, const AttributionSourceState& clientAttribution, int32_t devicePolicy,
-        /*out*/
-        sp<hardware::camera2::ICameraDeviceUser>* device) {
+        bool sharedMode, /*out*/sp<hardware::camera2::ICameraDeviceUser>* device) {
     ATRACE_CALL();
     RunThreadWithRealtimePriority priorityBump;
     Status ret = Status::ok();
@@ -2324,7 +2359,7 @@
             cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient,
             clientAttribution.attributionTag, clientUid, clientPid, API_2,
             /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
-            /*forceSlowJpegMode*/false, unresolvedCameraId, isNonSystemNdk, /*out*/client);
+            /*forceSlowJpegMode*/false, unresolvedCameraId, isNonSystemNdk, sharedMode, /*out*/client);
 
     if (!ret.isOk()) {
         logRejected(cameraId, callingPid, clientPackageName, toStdString(ret.toString8()));
@@ -2463,7 +2498,7 @@
         const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
         apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
         int rotationOverride, bool forceSlowJpegMode,
-        const std::string& originalCameraId, bool isNonSystemNdk, /*out*/sp<CLIENT>& device) {
+        const std::string& originalCameraId, bool isNonSystemNdk, bool sharedMode, /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
     int packageUid = (clientUid == USE_CALLING_UID) ?
@@ -2492,7 +2527,7 @@
 
         // Enforce client permissions and do basic validity checks
         if (!(ret = validateConnectLocked(cameraId, clientPackageName,
-                /*inout*/clientUid, /*inout*/clientPid)).isOk()) {
+                /*inout*/clientUid, /*inout*/clientPid, sharedMode)).isOk()) {
             return ret;
         }
 
@@ -2511,7 +2546,7 @@
         std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>> partial;
         if ((err = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
                 IInterface::asBinder(cameraCb), clientPackageName, oomScoreOffset,
-                systemNativeClient, /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
+                systemNativeClient, sharedMode, /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
             switch (err) {
                 case -ENODEV:
                     return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
@@ -2561,7 +2596,7 @@
                 clientFeatureId, cameraId, api1CameraId, facing,
                 orientation, getCallingPid(), clientUid, getpid(),
                 deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
-                rotationOverride, forceSlowJpegMode, originalCameraId,
+                rotationOverride, forceSlowJpegMode, originalCameraId, sharedMode,
                 /*out*/&tmp)).isOk()) {
             return ret;
         }
@@ -2807,7 +2842,7 @@
                 /*conflictingKeys*/ std::set<std::string>(), onlinePriority.getScore(),
                 onlineClientDesc->getOwnerId(), onlinePriority.getState(),
                 // native clients don't have offline processing support.
-                /*ommScoreOffset*/ 0, /*systemNativeClient*/false);
+                /*ommScoreOffset*/ 0, /*systemNativeClient*/false, /*sharedMode*/false);
         if (offlineClientDesc == nullptr) {
             ALOGE("%s: Offline client descriptor was NULL", __FUNCTION__);
             return BAD_VALUE;
@@ -3213,6 +3248,53 @@
     }
 }
 
+void CameraService::updateSharedClientAccessPriorities(std::vector<int> sharedClientPids) {
+    Mutex::Autolock lock(mServiceLock);
+    if (sharedClientPids.empty()) {
+        return;
+    }
+    std::vector<int> scores(sharedClientPids.size());
+    std::vector<int> states(sharedClientPids.size());
+    status_t err = ProcessInfoService::getProcessStatesScoresFromPids(sharedClientPids.size(),
+                &sharedClientPids[0], /*out*/&states[0], /*out*/&scores[0]);
+    if (err != OK) {
+        return;
+    }
+    for (size_t i = 0; i < sharedClientPids.size(); i++) {
+        auto clientDescriptorPtr = mActiveClientManager.getSharedClient(sharedClientPids[i]);
+        if (clientDescriptorPtr == nullptr) {
+            continue;
+        }
+        const auto& clientPriority = clientDescriptorPtr->getPriority();
+        int score = clientPriority.getScore();
+        int state = clientPriority.getState();
+        if ((score != scores[i])  || (state != states[i])){
+            clientDescriptorPtr->setPriority(resource_policy::ClientPriority(scores[i], states[i],
+                    false, 0));
+            notifySharedClientPrioritiesChanged(clientDescriptorPtr->getKey());
+        }
+    }
+}
+
+void CameraService::notifySharedClientPrioritiesChanged(const std::string& cameraId) {
+    auto primaryClientDesc = mActiveClientManager.getPrimaryClient(cameraId);
+    if (primaryClientDesc == nullptr) {
+        return;
+    }
+    auto primaryClient = primaryClientDesc->getValue();
+    if (primaryClient == nullptr) {
+        return;
+    }
+    auto highestPriorityClient = mActiveClientManager.getHighestPrioritySharedClient(cameraId);
+    if (highestPriorityClient == primaryClient) {
+        return;
+    }
+    highestPriorityClient->setPrimaryClient(true);
+    highestPriorityClient->notifyClientSharedAccessPriorityChanged(true);
+    primaryClient->setPrimaryClient(false);
+    primaryClient->notifyClientSharedAccessPriorityChanged(false);
+}
+
 Status CameraService::notifyDeviceStateChange(int64_t newState) {
     const int pid = getCallingPid();
     const int selfPid = getpid();
@@ -3740,6 +3822,22 @@
     updateAudioRestrictionLocked();
 }
 
+bool CameraService::isOnlyClient(const BasicClient* client) {
+    Mutex::Autolock lock(mServiceLock);
+    bool ret = true;
+    if (client != nullptr) {
+        std::string camId = client->mCameraIdStr;
+        for (const auto& i : mActiveClientManager.getAll()) {
+            auto clientSp = i->getValue();
+            auto curCamId = i->getKey();
+            if (!curCamId.compare(camId) && clientSp.get() != client) {
+                return false;
+            }
+        }
+    }
+    return ret;
+}
+
 bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
     bool ret = false;
     {
@@ -3800,20 +3898,22 @@
     return state;
 }
 
-sp<CameraService::BasicClient> CameraService::removeClientLocked(const std::string& cameraId) {
+std::vector<sp<CameraService::BasicClient>> CameraService::removeClientsLocked(
+        const std::string& cameraId) {
     // Remove from active clients list
-    auto clientDescriptorPtr = mActiveClientManager.remove(cameraId);
-    if (clientDescriptorPtr == nullptr) {
-        ALOGW("%s: Could not evict client, no client for camera ID %s", __FUNCTION__,
-                cameraId.c_str());
-        return sp<BasicClient>{nullptr};
+    std::vector<sp<CameraService::BasicClient>> clients;
+    std::vector<CameraService::DescriptorPtr> clientDescriptors;
+    clientDescriptors =  mActiveClientManager.removeAll(cameraId);
+    for (const auto& clientDescriptorPtr : clientDescriptors) {
+        if (clientDescriptorPtr != nullptr) {
+            sp<BasicClient> client = clientDescriptorPtr->getValue();
+            if (client.get() != nullptr) {
+                cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
+                clients.push_back(client);
+            }
+        }
     }
-
-    sp<BasicClient> client = clientDescriptorPtr->getValue();
-    if (client.get() != nullptr) {
-        cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
-    }
-    return client;
+    return clients;
 }
 
 void CameraService::doUserSwitch(const std::vector<int32_t>& newUserIds) {
@@ -4100,14 +4200,14 @@
         const std::string& cameraIdStr,
         int api1CameraId, int cameraFacing, int sensorOrientation,
         int clientPid, uid_t clientUid,
-        int servicePid, int rotationOverride) :
+        int servicePid, int rotationOverride, bool sharedMode) :
         CameraService::BasicClient(cameraService,
                 IInterface::asBinder(cameraClient),
                 attributionAndPermissionUtils,
                 clientPackageName, systemNativeClient, clientFeatureId,
                 cameraIdStr, cameraFacing, sensorOrientation,
                 clientPid, clientUid,
-                servicePid, rotationOverride),
+                servicePid, rotationOverride, sharedMode),
         mCameraId(api1CameraId)
 {
     int callingPid = getCallingPid();
@@ -4138,7 +4238,7 @@
         const std::string& clientPackageName, bool nativeClient,
         const std::optional<std::string>& clientFeatureId, const std::string& cameraIdStr,
         int cameraFacing, int sensorOrientation, int clientPid, uid_t clientUid,
-        int servicePid, int rotationOverride):
+        int servicePid, int rotationOverride, bool sharedMode):
         AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils),
         mDestructionStarted(false),
         mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing), mOrientation(sensorOrientation),
@@ -4147,7 +4247,7 @@
         mClientPid(clientPid), mClientUid(clientUid),
         mServicePid(servicePid),
         mDisconnected(false), mUidIsTrusted(false),
-        mRotationOverride(rotationOverride),
+        mRotationOverride(rotationOverride), mSharedMode(sharedMode),
         mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
         mRemoteBinder(remoteCallback),
         mOpsActive(false),
@@ -4189,8 +4289,15 @@
 
     sCameraService->removeByClient(this);
     sCameraService->logDisconnected(mCameraIdStr, mClientPid, mClientPackageName);
-    sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
-            mCameraIdStr);
+    if (!mSharedMode || (mSharedMode &&
+            sCameraService->isOnlyClient(this))) {
+        // Remove the HAL reference for the camera in either of the following scenarios :
+        // 1) Camera was opened in non-shared mode.
+        // 2) Camera was opened in shared mode and this is the last client using
+        //    the camera which is being disconnected
+        sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
+                mCameraIdStr);
+    }
 
     sp<IBinder> remote = getRemote();
     if (remote != nullptr) {
@@ -4198,8 +4305,11 @@
     }
 
     finishCameraOps();
-    // Notify flashlight that a camera device is closed.
-    sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
+    if (!mSharedMode || (mSharedMode &&
+            sCameraService->isOnlyClient(this))) {
+        // Notify flashlight that a camera device is closed.
+        sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
+    }
     ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(),
             mClientPid);
 
@@ -4361,8 +4471,12 @@
 
     sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);
 
+    if (mSharedMode) {
+        sCameraService->mUidPolicy->addSharedClientPid(getClientUid(), getClientPid());
+    }
+
     // Notify listeners of camera open/close status
-    sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
+    sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName, mSharedMode);
 
     return OK;
 }
@@ -4459,8 +4573,11 @@
                 StatusInternal::ENUMERATING, StatusInternal::NOT_PRESENT};
 
         // Transition to PRESENT if the camera is not in either of the rejected states
-        sCameraService->updateStatus(StatusInternal::PRESENT,
-                mCameraIdStr, rejected);
+        if (!mSharedMode || (mSharedMode
+                && sCameraService->isOnlyClient(this))) {
+            sCameraService->updateStatus(StatusInternal::PRESENT,
+                    mCameraIdStr, rejected);
+        }
     }
     // Always stop watching, even if no camera op is active
     if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
@@ -4470,8 +4587,12 @@
 
     sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid, /*closeCamera*/true);
 
+    if (mSharedMode) {
+        sCameraService->mUidPolicy->removeSharedClientPid(getClientUid(), getClientPid());
+    }
+
     // Notify listeners of camera open/close status
-    sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName);
+    sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName, mSharedMode);
 
     return OK;
 }
@@ -4547,6 +4668,25 @@
     disconnect();
 }
 
+status_t CameraService::BasicClient::isPrimaryClient(bool* isPrimary) {
+    ATRACE_CALL();
+    if (!mSharedMode) {
+        return INVALID_OPERATION;
+    }
+    *isPrimary = mIsPrimaryClient;
+    return OK;
+}
+
+status_t CameraService::BasicClient::setPrimaryClient(bool isPrimary) {
+    ATRACE_CALL();
+
+    if (!mSharedMode) {
+        return INVALID_OPERATION;
+    }
+    mIsPrimaryClient = isPrimary;
+    return OK;
+}
+
 // ----------------------------------------------------------------------------
 
 void CameraService::Client::notifyError(int32_t errorCode,
@@ -4667,21 +4807,33 @@
 void CameraService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState,
         int64_t procStateSeq __unused, int32_t capability __unused) {
     bool procStateChange = false;
+    std::vector<int> sharedPids;
     {
         Mutex::Autolock _l(mUidLock);
-        if (mMonitoredUids.find(uid) != mMonitoredUids.end() &&
-                mMonitoredUids[uid].procState != procState) {
-            mMonitoredUids[uid].procState = procState;
-            procStateChange = true;
+        if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
+            if (mMonitoredUids[uid].procState != procState) {
+                mMonitoredUids[uid].procState = procState;
+                procStateChange = true;
+            }
+            std::unordered_set<int> sharedClientPids = mMonitoredUids[uid].sharedClientPids;
+            if (!sharedClientPids.empty()) {
+              sharedPids.assign(sharedClientPids.begin(), sharedClientPids.end());
+            }
         }
     }
 
+    sp<CameraService> service = mService.promote();
     if (procStateChange) {
-        sp<CameraService> service = mService.promote();
         if (service != nullptr) {
             service->notifyMonitoredUids();
         }
     }
+
+    if (!sharedPids.empty()) {
+        if (service != nullptr) {
+            service->updateSharedClientAccessPriorities(sharedPids);
+        }
+    }
 }
 
 /**
@@ -4694,6 +4846,7 @@
  */
 void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
     std::unordered_set<uid_t> notifyUidSet;
+    std::vector<int> sharedPids;
     {
         Mutex::Autolock _l(mUidLock);
         auto it = mMonitoredUids.find(uid);
@@ -4717,15 +4870,26 @@
                 }
             }
             it->second.procAdj = adj;
+            std::unordered_set<int> sharedClientPids = it->second.sharedClientPids;
+            if (!sharedClientPids.empty()) {
+                sharedPids.assign(sharedClientPids.begin(), sharedClientPids.end());
+            }
         }
     }
 
+    sp<CameraService> service = mService.promote();
+
     if (notifyUidSet.size() > 0) {
-        sp<CameraService> service = mService.promote();
         if (service != nullptr) {
             service->notifyMonitoredUids(notifyUidSet);
         }
     }
+
+    if (!sharedPids.empty()) {
+        if (service != nullptr) {
+            service->updateSharedClientAccessPriorities(sharedPids);
+        }
+    }
 }
 
 /**
@@ -4859,6 +5023,20 @@
     updateOverrideUid(uid, callingPackage, false, false);
 }
 
+void CameraService::UidPolicy::addSharedClientPid(uid_t uid, int pid) {
+    Mutex::Autolock _l(mUidLock);
+    if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
+        mMonitoredUids[uid].sharedClientPids.insert(pid);
+    }
+}
+
+void CameraService::UidPolicy::removeSharedClientPid(uid_t uid, int pid) {
+    Mutex::Autolock _l(mUidLock);
+    if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
+        mMonitoredUids[uid].sharedClientPids.erase(pid);
+    }
+}
+
 void CameraService::UidPolicy::binderDied(const wp<IBinder>& /*who*/) {
     Mutex::Autolock _l(mUidLock);
     ALOGV("UidPolicy: ActivityManager has died");
@@ -5097,12 +5275,27 @@
 
 void CameraService::CameraState::setClientPackage(const std::string& clientPackage) {
     Mutex::Autolock lock(mStatusLock);
-    mClientPackage = clientPackage;
+    mClientPackages.clear();
+    mClientPackages.insert(clientPackage);
 }
 
 std::string CameraService::CameraState::getClientPackage() const {
     Mutex::Autolock lock(mStatusLock);
-    return mClientPackage;
+    if (!mClientPackages.empty()) {
+        std::set<std::string>::iterator it = mClientPackages.begin();
+        return *it;
+    }
+    return std::string();
+}
+
+void CameraService::CameraState::addClientPackage(const std::string& clientPackage) {
+    Mutex::Autolock lock(mStatusLock);
+    mClientPackages.insert(clientPackage);
+}
+
+void CameraService::CameraState::removeClientPackage(const std::string& clientPackage) {
+    Mutex::Autolock lock(mStatusLock);
+    mClientPackages.erase(clientPackage);
 }
 
 // ----------------------------------------------------------------------------
@@ -5150,6 +5343,48 @@
     return descriptor->getValue();
 }
 
+sp<CameraService::BasicClient> CameraService::CameraClientManager::getHighestPrioritySharedClient(
+        const std::string& id) const {
+    auto clientDescriptor = get(id);
+    if (clientDescriptor == nullptr) {
+        ALOGV("CameraService::CameraClientManager::no other clients are using same camera");
+        return sp<BasicClient>{nullptr};
+    }
+    if (!clientDescriptor->getSharedMode()) {
+        return sp<BasicClient>{nullptr};
+    }
+    resource_policy::ClientPriority highestPriority = clientDescriptor->getPriority();
+    sp<BasicClient> highestPriorityClient = clientDescriptor->getValue();
+    if (highestPriorityClient.get() == nullptr) {
+        return sp<BasicClient>{nullptr};
+    }
+    for (auto& i : getAll()) {
+        if ((i->getKey() == id) && (i->getSharedMode()) && (i->getPriority() < highestPriority)) {
+            highestPriority = i->getPriority();
+            highestPriorityClient = i->getValue();
+        }
+    }
+    return highestPriorityClient;
+}
+
+void CameraService::CameraClientManager::remove(const CameraService::DescriptorPtr& value) {
+    ClientManager::remove(value);
+    auto clientToRemove = value->getValue();
+    if ((clientToRemove.get() != nullptr) && clientToRemove->mSharedMode) {
+        bool primaryClient = false;
+        status_t ret = clientToRemove->isPrimaryClient(&primaryClient);
+        if ((ret == OK) && primaryClient) {
+            // Primary client is being removed. Find the next higher priority
+            // client to become primary client.
+            auto highestPriorityClient = getHighestPrioritySharedClient(value->getKey());
+            if (highestPriorityClient != nullptr) {
+                highestPriorityClient->setPrimaryClient(true);
+                highestPriorityClient->notifyClientSharedAccessPriorityChanged(true);
+            }
+        }
+    }
+}
+
 std::string CameraService::CameraClientManager::toString() const {
     auto all = getAll();
     std::ostringstream ret;
@@ -5195,14 +5430,14 @@
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const std::string& key, const sp<BasicClient>& value, int32_t cost,
         const std::set<std::string>& conflictingKeys, int32_t score, int32_t ownerId,
-        int32_t state, int32_t oomScoreOffset, bool systemNativeClient) {
+        int32_t state, int32_t oomScoreOffset, bool systemNativeClient, bool sharedMode) {
 
     int32_t score_adj = systemNativeClient ? kSystemNativeClientScore : score;
     int32_t state_adj = systemNativeClient ? kSystemNativeClientState : state;
 
     return std::make_shared<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>(
             key, value, cost, conflictingKeys, score_adj, ownerId, state_adj,
-            systemNativeClient, oomScoreOffset);
+            systemNativeClient, oomScoreOffset, sharedMode);
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
@@ -5211,7 +5446,7 @@
     return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
             partial->getConflicting(), partial->getPriority().getScore(),
             partial->getOwnerId(), partial->getPriority().getState(), oomScoreOffset,
-            systemNativeClient);
+            systemNativeClient, partial->getSharedMode());
 }
 
 // ----------------------------------------------------------------------------
@@ -5743,7 +5978,7 @@
 }
 
 void CameraService::updateOpenCloseStatus(const std::string& cameraId, bool open,
-        const std::string& clientPackageName) {
+        const std::string& clientPackageName, bool sharedMode) {
     auto state = getCameraState(cameraId);
     if (state == nullptr) {
         ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
@@ -5751,9 +5986,17 @@
         return;
     }
     if (open) {
-        state->setClientPackage(clientPackageName);
+        if (sharedMode) {
+            state->addClientPackage(clientPackageName);
+        } else {
+            state->setClientPackage(clientPackageName);
+        }
     } else {
-        state->setClientPackage(std::string());
+        if (sharedMode) {
+            state->removeClientPackage(clientPackageName);
+        } else {
+            state->setClientPackage(std::string());
+        }
     }
 
     // Get the device id and app-visible camera id for the given HAL-visible camera id.
@@ -5772,7 +6015,10 @@
             ret = it->getListener()->onCameraOpened(mappedCameraId, clientPackageName,
                     deviceId);
         } else {
-            ret = it->getListener()->onCameraClosed(mappedCameraId, deviceId);
+            if (!sharedMode || (sharedMode &&
+                    mActiveClientManager.getCameraClient(cameraId) == nullptr)) {
+                ret = it->getListener()->onCameraClosed(mappedCameraId, deviceId);
+            }
         }
 
         it->handleBinderStatus(ret,
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 0ac391d..ad6b6ba 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -181,7 +181,7 @@
             const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
             const std::string& cameraId, int scoreOffset, int targetSdkVersion,
             int rotationOverride, const AttributionSourceState& clientAttribution,
-            int32_t devicePolicy,
+            int32_t devicePolicy, bool sharedMode,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
 
@@ -384,6 +384,8 @@
         virtual void notifyError(int32_t errorCode,
                 const CaptureResultExtras& resultExtras) = 0;
 
+        virtual void notifyClientSharedAccessPriorityChanged(bool primaryClient) = 0;
+
         // Get the UID of the application client using this
         virtual uid_t getClientUid() const;
 
@@ -450,8 +452,12 @@
         virtual status_t injectSessionParams(
                 const hardware::camera2::impl::CameraMetadataNative& sessionParams) = 0;
 
+        status_t isPrimaryClient(/*out*/bool* isPrimary);
+
+        status_t setPrimaryClient(bool isPrimary);
+
     protected:
-        BasicClient(const sp<CameraService>& cameraService,
+       BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
                 std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
                 const std::string& clientPackageName,
@@ -463,7 +469,8 @@
                 int clientPid,
                 uid_t clientUid,
                 int servicePid,
-                int rotationOverride);
+                int rotationOverride,
+                bool sharedMode);
 
         virtual ~BasicClient();
 
@@ -487,6 +494,8 @@
         bool                            mDisconnected;
         bool                            mUidIsTrusted;
         int                             mRotationOverride;
+        bool                            mSharedMode;
+        bool                            mIsPrimaryClient;
 
         mutable Mutex                   mAudioRestrictionLock;
         int32_t                         mAudioRestriction;
@@ -578,7 +587,9 @@
                 int clientPid,
                 uid_t clientUid,
                 int servicePid,
-                int rotationOverride);
+                int rotationOverride,
+                bool sharedMode);
+
         ~Client();
 
         // return our camera client
@@ -638,6 +649,11 @@
         CameraClientManager();
         virtual ~CameraClientManager();
 
+        // Bring all remove() functions into scope
+        using ClientManager::remove;
+
+        virtual void remove(const DescriptorPtr& value) override;
+
         /**
          * Return a strong pointer to the active BasicClient for this camera ID, or an empty
          * if none exists.
@@ -645,6 +661,12 @@
         sp<CameraService::BasicClient> getCameraClient(const std::string& id) const;
 
         /**
+         * Return a strong pointer to the highest priority client among all the clients which
+         * have opened this camera ID in shared mode, or empty if none exists.
+         */
+        sp<CameraService::BasicClient> getHighestPrioritySharedClient(const std::string& id) const;
+
+        /**
          * Return a string describing the current state.
          */
         std::string toString() const;
@@ -655,7 +677,8 @@
         static DescriptorPtr makeClientDescriptor(const std::string& key,
                 const sp<BasicClient>& value, int32_t cost,
                 const std::set<std::string>& conflictingKeys, int32_t score,
-                int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient);
+                int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient,
+                bool sharedMode);
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
@@ -670,6 +693,15 @@
     int32_t updateAudioRestriction();
     int32_t updateAudioRestrictionLocked();
 
+    /**
+     * Returns true if the given client is the only client in the active clients list for a given
+     * camera.
+     *
+     * This method acquires mServiceLock.
+     */
+    bool isOnlyClient(const BasicClient* client);
+
+
 private:
 
     // TODO: b/263304156 update this to make use of a death callback for more
@@ -806,6 +838,10 @@
         void setClientPackage(const std::string& clientPackage);
         std::string getClientPackage() const;
 
+        void addClientPackage(const std::string& clientPackage);
+        void removeClientPackage(const std::string& clientPackage);
+        std::set<std::string> getClientPackages() const;
+
         /**
          * Return the unavailable physical ids for this device.
          *
@@ -818,7 +854,7 @@
         const int mCost;
         std::set<std::string> mConflicting;
         std::set<std::string> mUnavailablePhysicalIds;
-        std::string mClientPackage;
+        std::set<std::string> mClientPackages;
         mutable Mutex mStatusLock;
         CameraParameters mShimParams;
         const SystemCameraKind mSystemCameraKind;
@@ -855,6 +891,9 @@
         void registerMonitorUid(uid_t uid, bool openCamera);
         void unregisterMonitorUid(uid_t uid, bool closeCamera);
 
+        void addSharedClientPid(uid_t uid, int pid);
+        void removeSharedClientPid(uid_t uid, int pid);
+
         // Implementation of IServiceManager::LocalRegistrationCallback
         virtual void onServiceRegistration(const String16& name,
                         const sp<IBinder>& binder) override;
@@ -872,6 +911,9 @@
             int32_t procAdj;
             bool hasCamera;
             size_t refCount;
+            // This field is only valid when camera has been opened in shared mode, to adjust the
+            // priority of active clients based on the latest process score and state.
+            std::unordered_set<int> sharedClientPids;
         };
 
         Mutex mUidLock;
@@ -947,12 +989,11 @@
     void removeStates(const std::string& id);
 
     // Check if we can connect, before we acquire the service lock.
-    // If clientPid/clientUid are USE_CALLING_PID/USE_CALLING_UID, they will be overwritten with
-    // the calling pid/uid.
     binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
-            int clientUid, int clientPid) const;
+            int clientUid, int clientPid, bool sharedMode) const;
     binder::Status validateClientPermissionsLocked(const std::string& cameraId,
-            const std::string& clientName, int clientUid, int clientPid) const;
+            const std::string& clientName, int clientUid, int clientPid, bool sharedMode) const;
+
 
     // If clientPackageNameMaybe is empty, attempts to resolve the package name.
     std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const;
@@ -968,7 +1009,7 @@
     // Only call with with mServiceLock held.
     status_t handleEvictionsLocked(const std::string& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
-        const std::string& packageName, int scoreOffset, bool systemNativeClient,
+        const std::string& packageName, int scoreOffset, bool systemNativeClient, bool sharedMode,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial);
@@ -1013,7 +1054,7 @@
             const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
             apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
             int rotationOverride, bool forceSlowJpegMode,
-            const std::string& originalCameraId, bool isNonSystemNdk,
+            const std::string& originalCameraId, bool isNonSystemNdk, bool sharedMode,
             /*out*/sp<CLIENT>& device);
 
     // Lock guarding camera service state
@@ -1110,6 +1151,18 @@
             int oomScoreOffset, bool systemNativeClient);
 
     /**
+     * When multiple clients open the camera in shared mode, adjust the priority of active clients
+     * based on the latest process score and state.
+     */
+    void updateSharedClientAccessPriorities(std::vector<int> sharedClientPids);
+
+    /**
+     * Update all clients on any changes in the primary or secondary client status if the priority
+     * of any client changes when multiple clients are sharing a camera.
+     */
+    void notifySharedClientPrioritiesChanged(const std::string& cameraId);
+
+    /**
      * Returns the underlying camera Id string mapped to a camera id int
      * Empty string is returned when the cameraIdInt is invalid.
      */
@@ -1122,12 +1175,12 @@
     std::string cameraIdIntToStrLocked(int cameraIdInt, int32_t deviceId, int32_t devicePolicy);
 
     /**
-     * Remove a single client corresponding to the given camera id from the list of active clients.
+     * Remove all the clients corresponding to the given camera id from the list of active clients.
      * If none exists, return an empty strongpointer.
      *
      * This method must be called with mServiceLock held.
      */
-    sp<CameraService::BasicClient> removeClientLocked(const std::string& cameraId);
+    std::vector<sp<CameraService::BasicClient>> removeClientsLocked(const std::string& cameraId);
 
     /**
      * Handle a notification that the current device user has changed.
@@ -1335,7 +1388,7 @@
      * This method acqiures mStatusListenerLock.
      */
     void updateOpenCloseStatus(const std::string& cameraId, bool open,
-            const std::string& packageName);
+            const std::string& packageName, bool sharedMode);
 
     // flashlight control
     sp<CameraFlashlight> mFlashlight;
@@ -1508,9 +1561,10 @@
             int clientPid, uid_t clientUid, int servicePid,
             std::pair<int, IPCTransport> deviceVersionAndIPCTransport, apiLevel effectiveApiLevel,
             bool overrideForPerfClass, int rotationOverride, bool forceSlowJpegMode,
-            const std::string& originalCameraId,
+            const std::string& originalCameraId, bool sharedMode,
             /*out*/ sp<BasicClient>* client);
 
+
     static std::string toString(std::set<userid_t> intSet);
     static int32_t mapToInterface(TorchModeStatus status);
     static StatusInternal mapToInternal(CameraDeviceStatus status);
@@ -1524,6 +1578,9 @@
 
     void disconnectClient(const std::string& id, sp<BasicClient> clientToDisconnect);
 
+    void disconnectClients(const std::string& id,
+            std::vector<sp<BasicClient>> clientsToDisconnect);
+
     // Regular online and offline devices must not be in conflict at camera service layer.
     // Use separate keys for offline devices.
     static const std::string kOfflineDevice;
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
index e648a36..eac61e7 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
@@ -79,6 +79,12 @@
     return binder::Status::ok();
 }
 
+binder::Status AidlCameraDeviceCallbacks::onClientSharedAccessPriorityChanged(bool primaryClient) {
+    auto ret = mBase->onClientSharedAccessPriorityChanged(primaryClient);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onClientSharedAccessPriorityChanged")
+    return binder::Status::ok();
+ }
+
 binder::Status AidlCameraDeviceCallbacks::onDeviceIdle() {
     auto ret = mBase->onDeviceIdle();
     LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceIdle")
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
index 5cff5b3..07bf7d8 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
@@ -75,6 +75,8 @@
 
     binder::Status onRequestQueueEmpty() override;
 
+    binder::Status onClientSharedAccessPriorityChanged(bool primaryClient) override;
+
     status_t linkToDeath(const sp<DeathRecipient>& recipient, void* cookie,
                          uint32_t flags) override;
     status_t unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
index 9e6a925..eacfeac 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -192,6 +192,30 @@
     return fromUStatus(ret);
 }
 
+ndk::ScopedAStatus AidlCameraDeviceUser::isPrimaryClient(bool* _aidl_return) {
+    bool isPrimary;
+    UStatus ret = mDeviceRemote->isPrimaryClient(&isPrimary);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed to get isPrimaryClient: %s", __FUNCTION__, ret.toString8().c_str());
+    }
+    *_aidl_return = isPrimary;
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::startStreaming(
+        const std::vector<int32_t>& in_streamIdxArray,
+        const std::vector<int32_t>& in_surfaceIdxArray, SSubmitInfo* _aidl_return){
+    USubmitInfo submitInfo;
+    UStatus ret = mDeviceRemote->startStreaming(in_streamIdxArray, in_surfaceIdxArray, &submitInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed to start streaming: %s", __FUNCTION__, ret.toString8().c_str());
+        return fromUStatus(ret);
+    }
+    mRequestId = submitInfo.mRequestId;
+    convertToAidl(submitInfo, _aidl_return);
+    return ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus AidlCameraDeviceUser::flush(int64_t* _aidl_return) {
     UStatus ret = mDeviceRemote->flush(_aidl_return);
     return fromUStatus(ret);
@@ -278,4 +302,4 @@
     return true;
 }
 
-} // namespace android::frameworks::cameraservice::device::implementation
\ No newline at end of file
+} // namespace android::frameworks::cameraservice::device::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
index 8014951..25464a5 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
@@ -97,6 +97,11 @@
         return mCaptureResultMetadataQueue;
     }
 
+    ndk::ScopedAStatus isPrimaryClient(bool* _aidl_return) override;
+
+    ndk::ScopedAStatus startStreaming(const std::vector<int32_t>& in_streamIdxArray,
+            const std::vector<int32_t>& in_surfaceIdxArray, SSubmitInfo* _aidl_return) override;
+
   private:
     bool initDevice();
 
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index 7f674bd..d683d61 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -30,6 +30,9 @@
 #include <hidl/HidlTransportSupport.h>
 #include <utils/AttributionAndPermissionUtils.h>
 #include <utils/Utils.h>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
 
 namespace android::frameworks::cameraservice::service::implementation {
 
@@ -131,10 +134,25 @@
 
     return ScopedAStatus::ok();
 }
+
 ndk::ScopedAStatus AidlCameraService::connectDevice(
         const std::shared_ptr<SICameraDeviceCallback>& in_callback,
         const std::string& in_cameraId,
         std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
+    return connectDeviceImpl(in_callback, in_cameraId, /*sharedMode*/false, _aidl_return);
+}
+
+ndk::ScopedAStatus AidlCameraService::connectDeviceV2(
+        const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+        const std::string& in_cameraId, bool sharedMode,
+        std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
+      return connectDeviceImpl(in_callback, in_cameraId, sharedMode, _aidl_return);
+}
+
+ndk::ScopedAStatus AidlCameraService::connectDeviceImpl(
+        const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+        const std::string& in_cameraId, bool sharedMode,
+        std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
     // Here, we first get NDK ICameraDeviceUser from mCameraService, then save
     // that interface in the newly created AidlCameraDeviceUser impl class.
     if (mCameraService == nullptr) {
@@ -164,6 +182,7 @@
             ROTATION_OVERRIDE_NONE,
             clientAttribution,
             /* devicePolicy= */ 0,
+            sharedMode,
             &unstableDevice);
     if (!serviceRet.isOk()) {
         ALOGE("%s: Unable to connect to camera device: %s", __FUNCTION__,
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.h b/services/camera/libcameraservice/aidl/AidlCameraService.h
index 4c67ac7..80e965d 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.h
@@ -60,6 +60,9 @@
     ndk::ScopedAStatus removeListener(
             const std::shared_ptr<SICameraServiceListener>& in_listener) override;
 
+    ndk::ScopedAStatus connectDeviceV2(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+                                     const std::string& in_cameraId, bool sharedMode,
+                                     std::shared_ptr<SICameraDeviceUser>* _aidl_return);
   private:
     void addToListenerCacheLocked(std::shared_ptr<SICameraServiceListener> stableCsListener,
                                   sp<hardware::ICameraServiceListener> csListener);
@@ -70,6 +73,9 @@
     SStatus addListenerInternal(const std::shared_ptr<SICameraServiceListener>& listener,
                                 std::vector<hardware::CameraStatus>* cameraStatusAndIds);
 
+    ndk::ScopedAStatus connectDeviceImpl(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+            const std::string& in_cameraId, bool sharedMode,
+            std::shared_ptr<SICameraDeviceUser>* _aidl_return);
 
     ::android::CameraService* mCameraService;
 
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
index a7c32e3..c0dc688 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -75,6 +75,11 @@
                          uint32_t flags) override;
     status_t unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
                            wp<DeathRecipient>* outRecipient) override;
+    binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageId*/, int32_t /*deviceId*/, bool /*primaryClient*/) {
+         // empty implementation
+        return binder::Status::ok();
+    }
 
   private:
     std::shared_ptr<SICameraServiceListener> mBase;
@@ -86,4 +91,4 @@
 
 } // android
 
-#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
\ No newline at end of file
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
diff --git a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index b07d8d5..b8d88c0 100644
--- a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -93,6 +93,10 @@
           ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL,
           ANDROID_INFO_SESSION_CONFIGURATION_QUERY_VERSION,
         } },
+      {36, {
+          ANDROID_SHARED_SESSION_COLOR_SPACE,
+          ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
+        } },
 };
 
 /**
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 861414f..ae68a72 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -70,12 +70,13 @@
         int servicePid,
         bool overrideForPerfClass,
         int rotationOverride,
-        bool forceSlowJpegMode):
+        bool forceSlowJpegMode,
+        bool sharedMode):
         Camera2ClientBase(cameraService, cameraClient, cameraServiceProxyWrapper,
                 attributionAndPermissionUtils, clientPackageName,
                 false/*systemNativeClient - since no ndk for api1*/, clientFeatureId,
                 cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
-                clientUid, servicePid, overrideForPerfClass, rotationOverride,
+                clientUid, servicePid, overrideForPerfClass, rotationOverride, sharedMode,
                 /*legacyClient*/ true),
         mParameters(api1CameraId, cameraFacing),
         mLatestRequestIds(kMaxRequestIds),
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index a0c9f2d..e7ff923 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -115,7 +115,7 @@
             int servicePid,
             bool overrideForPerfClass,
             int rotationOverride,
-            bool forceSlowJpegMode);
+            bool forceSlowJpegMode, bool sharedMode);
 
     virtual ~Camera2Client();
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index f469aad..888875e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -54,6 +54,7 @@
 using namespace camera2;
 using namespace camera3;
 using camera3::camera_stream_rotation_t::CAMERA_STREAM_ROTATION_0;
+using hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
 
 namespace flags = com::android::internal::camera::flags;
 
@@ -71,7 +72,8 @@
         int clientPid,
         uid_t clientUid,
         int servicePid,
-        int rotationOverride) :
+        int rotationOverride,
+        bool sharedMode) :
     BasicClient(cameraService,
             IInterface::asBinder(remoteCallback),
             attributionAndPermissionUtils,
@@ -84,7 +86,8 @@
             clientPid,
             clientUid,
             servicePid,
-            rotationOverride),
+            rotationOverride,
+            sharedMode),
     mRemoteCallback(remoteCallback) {
 }
 
@@ -105,14 +108,16 @@
         int servicePid,
         bool overrideForPerfClass,
         int rotationOverride,
-        const std::string& originalCameraId) :
+        const std::string& originalCameraId,
+        bool sharedMode) :
     Camera2ClientBase(cameraService, remoteCallback, cameraServiceProxyWrapper,
             attributionAndPermissionUtils, clientPackageName,
             systemNativeClient, clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing,
             sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass,
-            rotationOverride),
+            rotationOverride, sharedMode),
     mInputStream(),
     mStreamingRequestId(REQUEST_ID_NONE),
+    mStreamingRequestLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES),
     mRequestIdCounter(0),
     mOverrideForPerfClass(overrideForPerfClass),
     mOriginalCameraId(originalCameraId) {
@@ -136,13 +141,23 @@
         return res;
     }
 
-    mFrameProcessor = new FrameProcessorBase(mDevice);
-    std::string threadName = std::string("CDU-") + mCameraIdStr + "-FrameProc";
-    res = mFrameProcessor->run(threadName.c_str());
-    if (res != OK) {
-        ALOGE("%s: Unable to start frame processor thread: %s (%d)",
-                __FUNCTION__, strerror(-res), res);
-        return res;
+    if (mSharedMode) {
+        // In shared camera device mode, there can be more than one clients and
+        // frame processor thread is started by shared camera device.
+        mFrameProcessor = mDevice->getSharedFrameProcessor();
+        if (mFrameProcessor == nullptr) {
+            ALOGE("%s: Unable to start frame processor thread", __FUNCTION__);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        mFrameProcessor = new FrameProcessorBase(mDevice);
+        std::string threadName = std::string("CDU-") + mCameraIdStr + "-FrameProc";
+        res = mFrameProcessor->run(threadName.c_str());
+        if (res != OK) {
+            ALOGE("%s: Unable to start frame processor thread: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
     }
 
     mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
@@ -268,6 +283,98 @@
     return intersection;
 }
 
+binder::Status CameraDeviceClient::startStreaming(const std::vector<int>& streamIds,
+            const std::vector<int>& surfaceIds,
+            /*out*/
+            hardware::camera2::utils::SubmitInfo *submitInfo) {
+    ATRACE_CALL();
+    ALOGV("%s-start of function. Stream list size %zu. Surface list size %zu", __FUNCTION__,
+            streamIds.size(), surfaceIds.size());
+
+    binder::Status res = binder::Status::ok();
+    status_t err;
+    if ( !(res = checkPidStatus(__FUNCTION__) ).isOk()) {
+        return res;
+    }
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    if (!mSharedMode) {
+        ALOGE("%s: Camera %s: Invalid operation.", __FUNCTION__, mCameraIdStr.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, "Invalid operation");
+    }
+
+    if (streamIds.empty() || surfaceIds.empty()) {
+        ALOGE("%s: Camera %s: Sent empty streamIds or surface Ids. Rejecting request.",
+              __FUNCTION__, mCameraIdStr.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty Stream or surface Ids");
+    }
+
+    if (streamIds.size() != surfaceIds.size()) {
+        ALOGE("%s: Camera %s: Sent different size array for stream and surface Ids.",
+              __FUNCTION__, mCameraIdStr.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Stream and surface Ids are not of same size");
+    }
+
+    submitInfo->mRequestId = mRequestIdCounter;
+    SurfaceMap surfaceMap;
+    Vector<int32_t> outputStreamIds;
+    for (size_t i = 0; i < streamIds.size(); i++) {
+        int streamId = streamIds[i];
+        int surfaceIdx = surfaceIds[i];
+
+        ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
+        if (index < 0) {
+            ALOGE("%s: Camera %s: Tried to start streaming with a surface that"
+                    " we have not called createStream on: stream %d",
+                    __FUNCTION__, mCameraIdStr.c_str(), streamId);
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Start streaming targets Surface that is not part of current capture session");
+        }
+
+        const auto& surfaces = mConfiguredOutputs.valueAt(index).getGraphicBufferProducers();
+        if ((size_t)surfaceIdx >= surfaces.size()) {
+            ALOGE("%s: Camera %s: Tried to start streaming with a surface that"
+                    " we have not called createStream on: stream %d, surfaceIdx %d",
+                     __FUNCTION__, mCameraIdStr.c_str(), streamId, surfaceIdx);
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Start streaming targets Surface has invalid surface index");
+        }
+
+        res = insertGbpLocked(surfaces[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
+
+        if (!res.isOk()) {
+            return res;
+        }
+    }
+
+    mRequestIdCounter++;
+    int sharedReqID;
+
+    err = mDevice->startStreaming(submitInfo->mRequestId, surfaceMap, &sharedReqID,
+            &(submitInfo->mLastFrameNumber));
+    if (err != OK) {
+        std::string msg = fmt::sprintf(
+            "Camera %s:  Got error %s (%d) after trying to start streaming request",
+            mCameraIdStr.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+    } else {
+        Mutex::Autolock idLock(mStreamingRequestIdLock);
+        mStreamingRequestId = submitInfo->mRequestId;
+        mSharedStreamingRequest = {sharedReqID, submitInfo->mRequestId};
+    }
+
+    markClientActive();
+    ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.c_str());
+    return binder::Status::ok();
+}
+
 binder::Status CameraDeviceClient::submitRequestList(
         const std::vector<hardware::camera2::CaptureRequest>& requests,
         bool streaming,
@@ -294,6 +401,12 @@
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
     }
 
+    if (mSharedMode && !mIsPrimaryClient) {
+        ALOGE("%s: Camera %s: This client is not a primary client of the shared camera device.",
+              __FUNCTION__, mCameraIdStr.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, "Invalid Operation.");
+    }
+
     List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
     std::list<SurfaceMap> surfaceMapList;
     submitInfo->mRequestId = mRequestIdCounter;
@@ -564,9 +677,16 @@
     }
     mRequestIdCounter++;
 
+    int32_t sharedReqID;
     if (streaming) {
-        err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
-                &(submitInfo->mLastFrameNumber));
+        if (mSharedMode) {
+            err = mDevice->setSharedStreamingRequest(*metadataRequestList.begin(),
+                    *surfaceMapList.begin(), &sharedReqID, &(submitInfo->mLastFrameNumber));
+        } else {
+            err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
+                    &(submitInfo->mLastFrameNumber));
+        }
+
         if (err != OK) {
             std::string msg = fmt::sprintf(
                 "Camera %s:  Got error %s (%d) after trying to set streaming request",
@@ -577,10 +697,19 @@
         } else {
             Mutex::Autolock idLock(mStreamingRequestIdLock);
             mStreamingRequestId = submitInfo->mRequestId;
+            if (mSharedMode) {
+                mSharedStreamingRequest = {sharedReqID, submitInfo->mRequestId};
+                markClientActive();
+            }
         }
     } else {
-        err = mDevice->captureList(metadataRequestList, surfaceMapList,
-                &(submitInfo->mLastFrameNumber));
+        if (mSharedMode) {
+            err = mDevice->setSharedCaptureRequest(*metadataRequestList.begin(),
+                    *surfaceMapList.begin(), &sharedReqID, &(submitInfo->mLastFrameNumber));
+         } else {
+            err = mDevice->captureList(metadataRequestList, surfaceMapList,
+                    &(submitInfo->mLastFrameNumber));
+        }
         if (err != OK) {
             std::string msg = fmt::sprintf(
                 "Camera %s: Got error %s (%d) after trying to submit capture request",
@@ -589,6 +718,10 @@
             res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
                     msg.c_str());
         }
+        if (mSharedMode) {
+            mSharedRequestMap[sharedReqID] = submitInfo->mRequestId;
+            markClientActive();
+        }
         ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
     }
 
@@ -622,12 +755,19 @@
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
-    err = mDevice->clearStreamingRequest(lastFrameNumber);
+    if (mSharedMode) {
+        err = mDevice->clearSharedStreamingRequest(lastFrameNumber);
+    } else {
+        err = mDevice->clearStreamingRequest(lastFrameNumber);
+    }
 
     if (err == OK) {
         ALOGV("%s: Camera %s: Successfully cleared streaming request",
                 __FUNCTION__, mCameraIdStr.c_str());
         mStreamingRequestId = REQUEST_ID_NONE;
+        if (mSharedMode) {
+            mStreamingRequestLastFrameNumber = *lastFrameNumber;
+        }
     } else {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error clearing streaming request: %s (%d)",
@@ -638,9 +778,17 @@
 }
 
 binder::Status CameraDeviceClient::beginConfigure() {
-    // TODO: Implement this.
     ATRACE_CALL();
-    ALOGV("%s: Not implemented yet.", __FUNCTION__);
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+    status_t res = mDevice->beginConfigure();
+    if (res != OK) {
+        std::string msg = fmt::sprintf("Camera %s: Error beginning stream configuration: %s (%d)",
+                mCameraIdStr.c_str(), strerror(-res), res);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+    }
     return binder::Status::ok();
 }
 
@@ -673,6 +821,12 @@
         return res;
     }
 
+    if (mSharedMode) {
+        // For shared camera session, streams are already configured
+        // earlier, hence no need to do it here.
+        return res;
+    }
+
     status_t err = mDevice->configureStreams(sessionParams, operatingMode);
     if (err == BAD_VALUE) {
         std::string msg = fmt::sprintf("Camera %s: Unsupported set of inputs/outputs provided",
@@ -796,6 +950,7 @@
 
     bool isInput = false;
     std::vector<sp<IBinder>> surfaces;
+    std::vector<size_t> removedSurfaceIds;
     ssize_t dIndex = NAME_NOT_FOUND;
     ssize_t compositeIndex  = NAME_NOT_FOUND;
 
@@ -806,6 +961,9 @@
         for (size_t i = 0; i < mStreamMap.size(); ++i) {
             if (streamId == mStreamMap.valueAt(i).streamId()) {
                 surfaces.push_back(mStreamMap.keyAt(i));
+                if (mSharedMode) {
+                    removedSurfaceIds.push_back(mStreamMap.valueAt(i).surfaceId());
+                }
             }
         }
 
@@ -833,8 +991,14 @@
         }
     }
 
-    // Also returns BAD_VALUE if stream ID was not valid
-    status_t err = mDevice->deleteStream(streamId);
+
+    status_t err;
+    if (mSharedMode) {
+        err = mDevice->removeSharedSurfaces(streamId, removedSurfaceIds);
+    } else {
+        // Also returns BAD_VALUE if stream ID was not valid
+        err = mDevice->deleteStream(streamId);
+    }
 
     if (err != OK) {
         std::string msg = fmt::sprintf("Camera %s: Unexpected error %s (%d) when deleting stream "
@@ -929,6 +1093,7 @@
 
     std::vector<sp<Surface>> surfaces;
     std::vector<sp<IBinder>> binders;
+    std::vector<OutputStreamInfo> streamInfos;
     status_t err;
 
     // Create stream for deferred surface case.
@@ -967,51 +1132,67 @@
 
         binders.push_back(IInterface::asBinder(bufferProducer));
         surfaces.push_back(surface);
+        if (mSharedMode) {
+            streamInfos.push_back(streamInfo);
+        }
     }
 
-    // If mOverrideForPerfClass is true, do not fail createStream() for small
-    // JPEG sizes because existing createSurfaceFromGbp() logic will find the
-    // closest possible supported size.
-
     int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
     std::vector<int> surfaceIds;
-    bool isDepthCompositeStream =
-            camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
-    bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
-    bool isJpegRCompositeStream =
-        camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0]) &&
-        !mDevice->isCompositeJpegRDisabled();
-    if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
-        sp<CompositeStream> compositeStream;
-        if (isDepthCompositeStream) {
-            compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
-        } else if (isHeicCompositeStream) {
-            compositeStream = new camera3::HeicCompositeStream(mDevice, getRemoteCallback());
-        } else {
-            compositeStream = new camera3::JpegRCompositeStream(mDevice, getRemoteCallback());
+    if (mSharedMode) {
+        std::vector<int> streamIds;
+        err = mDevice->getSharedStreamIds(streamInfo, streamIds);
+        if (err == OK) {
+            for (auto id: streamIds) {
+              if (!mStreamInfoMap.contains(id)) {
+                streamId = id;
+                break;
+              }
+            }
+            if (streamId == camera3::CAMERA3_STREAM_ID_INVALID) {
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "OutputConfiguration isn't valid!");
+            }
+            err = mDevice->addSharedSurfaces(streamId, streamInfos, surfaces, &surfaceIds);
         }
-
-        err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
+    } else {
+        bool isDepthCompositeStream =
+                camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
+        bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
+        bool isJpegRCompositeStream =
+            camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0]) &&
+            !mDevice->isCompositeJpegRDisabled();
+        if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
+            sp<CompositeStream> compositeStream;
+            if (isDepthCompositeStream) {
+                compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
+            } else if (isHeicCompositeStream) {
+                compositeStream = new camera3::HeicCompositeStream(mDevice, getRemoteCallback());
+            } else {
+                compositeStream = new camera3::JpegRCompositeStream(mDevice, getRemoteCallback());
+            }
+            err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
                 streamInfo.height, streamInfo.format,
                 static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
                 &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
                 outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
                 streamInfo.colorSpace, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
                 useReadoutTimestamp);
-        if (err == OK) {
-            Mutex::Autolock l(mCompositeLock);
-            mCompositeStreamMap.add(IInterface::asBinder(surfaces[0]->getIGraphicBufferProducer()),
-                    compositeStream);
+            if (err == OK) {
+                Mutex::Autolock l(mCompositeLock);
+                mCompositeStreamMap.add(IInterface::asBinder(surfaces[0]->getIGraphicBufferProducer()),
+                        compositeStream);
+            }
+        } else {
+            err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
+                    streamInfo.height, streamInfo.format, streamInfo.dataSpace,
+                    static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
+                    &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
+                    outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
+                    /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
+                    streamInfo.timestampBase, streamInfo.mirrorMode, streamInfo.colorSpace,
+                    useReadoutTimestamp);
         }
-    } else {
-        err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
-                streamInfo.height, streamInfo.format, streamInfo.dataSpace,
-                static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
-                &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
-                outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
-                /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
-                streamInfo.timestampBase, streamInfo.mirrorMode, streamInfo.colorSpace,
-                useReadoutTimestamp);
     }
 
     if (err != OK) {
@@ -1521,6 +1702,10 @@
                 "Camera %s: Error flushing device: %s (%d)", mCameraIdStr.c_str(), strerror(-err),
                 err);
     }
+    if (mSharedMode) {
+        mSharedRequestMap.clear();
+        mStreamingRequestLastFrameNumber = *lastFrameNumber;
+    }
     return res;
 }
 
@@ -1805,6 +1990,17 @@
     return binder::Status::ok();
 }
 
+binder::Status CameraDeviceClient::isPrimaryClient(/*out*/bool* isPrimary) {
+    ATRACE_CALL();
+    binder::Status res =  binder::Status::ok();
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+    if (isPrimary != nullptr) {
+        status_t ret = BasicClient::isPrimaryClient(isPrimary);
+        return  binder::Status::fromStatusT(ret);
+    }
+    return res;
+}
+
 status_t CameraDeviceClient::setCameraServiceWatchdog(bool enabled) {
     return mDevice->setCameraServiceWatchdog(enabled);
 }
@@ -1937,7 +2133,7 @@
         offlineClient = new CameraOfflineSessionClient(sCameraService,
                 offlineSession, offlineCompositeStreamMap, cameraCb, mAttributionAndPermissionUtils,
                 mClientPackageName, mClientFeatureId, mCameraIdStr, mCameraFacing, mOrientation,
-                mClientPid, mClientUid, mServicePid);
+                mClientPid, mClientUid, mServicePid, /*sharedMode*/false);
         ret = sCameraService->addOfflineClient(mCameraIdStr, offlineClient);
     }
 
@@ -2047,8 +2243,26 @@
                                      const CaptureResultExtras& resultExtras) {
     // Thread safe. Don't bother locking.
     sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
-
     bool skipClientNotification = false;
+    if (mSharedMode && (resultExtras.requestId != -1)) {
+        int clientReqId;
+        bool matchStreamingRequest = matchSharedStreamingRequest(resultExtras.requestId);
+        bool matchCaptureRequest = matchSharedCaptureRequest(resultExtras.requestId);
+        if (matchStreamingRequest) {
+            clientReqId = mSharedStreamingRequest.second;
+        } else if (matchCaptureRequest) {
+            clientReqId = mSharedRequestMap[resultExtras.requestId];
+            mSharedRequestMap.erase(resultExtras.requestId);
+        } else {
+            return;
+        }
+        CaptureResultExtras mutableResultExtras = resultExtras;
+        mutableResultExtras.requestId = clientReqId;
+        if (remoteCb != 0) {
+            remoteCb->onDeviceError(errorCode, mutableResultExtras);
+        }
+        return;
+    }
     {
         // Access to the composite stream map must be synchronized
         Mutex::Autolock l(mCompositeLock);
@@ -2111,10 +2325,30 @@
         nsecs_t timestamp) {
     // Thread safe. Don't bother locking.
     sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
-    if (remoteCb != 0) {
-        remoteCb->onCaptureStarted(resultExtras, timestamp);
+    CaptureResultExtras mutableResultExtras = resultExtras;
+    if (mSharedMode) {
+        int clientReqId;
+        bool matchStreamingRequest = matchSharedStreamingRequest(resultExtras.requestId);
+        bool matchCaptureRequest = matchSharedCaptureRequest(resultExtras.requestId);
+        if (matchStreamingRequest) {
+            clientReqId = mSharedStreamingRequest.second;
+        } else if (matchCaptureRequest) {
+            clientReqId = mSharedRequestMap[resultExtras.requestId];
+        } else {
+            return;
+        }
+        mutableResultExtras.requestId = clientReqId;
     }
-    Camera2ClientBase::notifyShutter(resultExtras, timestamp);
+
+    if (remoteCb != 0) {
+        remoteCb->onCaptureStarted(mutableResultExtras, timestamp);
+    }
+    Camera2ClientBase::notifyShutter(mutableResultExtras, timestamp);
+    if (mSharedMode) {
+        // When camera is opened in shared mode, composite streams are not
+        // supported.
+        return;
+    }
 
     // Access to the composite stream map must be synchronized
     Mutex::Autolock l(mCompositeLock);
@@ -2140,46 +2374,79 @@
     }
 }
 
+void CameraDeviceClient::notifyClientSharedAccessPriorityChanged(bool primaryClient) {
+    // Thread safe. Don't bother locking.
+    sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
+    if (remoteCb != 0) {
+        remoteCb->onClientSharedAccessPriorityChanged(primaryClient);
+    }
+}
+
 void CameraDeviceClient::detachDevice() {
     if (mDevice == 0) return;
 
     nsecs_t startTime = systemTime();
-    ALOGV("Camera %s: Stopping processors", mCameraIdStr.c_str());
-
     if (mFrameProcessor.get() != nullptr) {
-        mFrameProcessor->removeListener(
-                camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
-                camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID, /*listener*/this);
-        mFrameProcessor->requestExit();
-        ALOGV("Camera %s: Waiting for threads", mCameraIdStr.c_str());
-        mFrameProcessor->join();
-        ALOGV("Camera %s: Disconnecting device", mCameraIdStr.c_str());
+            mFrameProcessor->removeListener(
+                    camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+                    camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID, /*listener*/this);
     }
 
-    // WORKAROUND: HAL refuses to disconnect while there's streams in flight
-    {
-        int64_t lastFrameNumber;
-        status_t code;
-        if ((code = mDevice->flush(&lastFrameNumber)) != OK) {
-            ALOGE("%s: flush failed with code 0x%x", __FUNCTION__, code);
-        }
-
-        if ((code = mDevice->waitUntilDrained()) != OK) {
-            ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
-                  code);
-        }
-    }
-
-    {
-        Mutex::Autolock l(mCompositeLock);
-        for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
-            auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
-            if (ret != OK) {
-                ALOGE("%s: Failed removing composite stream  %s (%d)", __FUNCTION__,
-                        strerror(-ret), ret);
+    if (mSharedMode) {
+        for (auto streamInfo : mStreamInfoMap) {
+            int streamToDelete = streamInfo.first;
+            std::vector<size_t> removedSurfaceIds;
+            for (size_t i = 0; i < mStreamMap.size(); ++i) {
+                if (streamToDelete == mStreamMap.valueAt(i).streamId()) {
+                    removedSurfaceIds.push_back(mStreamMap.valueAt(i).surfaceId());
+                }
+            }
+            status_t err = mDevice->removeSharedSurfaces(streamToDelete, removedSurfaceIds);
+            if (err != OK) {
+                std::string msg = fmt::sprintf("Camera %s: Unexpected error %s (%d) when removing"
+                        "shared surfaces from stream %d", mCameraIdStr.c_str(), strerror(-err),
+                        err, streamToDelete);
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
             }
         }
-        mCompositeStreamMap.clear();
+    }
+
+    if (!mSharedMode ||
+            (mSharedMode && sCameraService->isOnlyClient(this))){
+        ALOGV("Camera %s: Stopping processors", mCameraIdStr.c_str());
+
+        if (mFrameProcessor.get() != nullptr) {
+            mFrameProcessor->requestExit();
+            ALOGV("Camera %s: Waiting for threads", mCameraIdStr.c_str());
+            mFrameProcessor->join();
+            ALOGV("Camera %s: Disconnecting device", mCameraIdStr.c_str());
+        }
+
+        // WORKAROUND: HAL refuses to disconnect while there's streams in flight
+        {
+            int64_t lastFrameNumber;
+            status_t code;
+            if ((code = mDevice->flush(&lastFrameNumber)) != OK) {
+                ALOGE("%s: flush failed with code 0x%x", __FUNCTION__, code);
+            }
+
+            if ((code = mDevice->waitUntilDrained()) != OK) {
+                ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
+                        code);
+            }
+        }
+
+        {
+            Mutex::Autolock l(mCompositeLock);
+            for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+                auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
+                if (ret != OK) {
+                    ALOGE("%s: Failed removing composite stream  %s (%d)", __FUNCTION__,
+                            strerror(-ret), ret);
+                }
+            }
+            mCompositeStreamMap.clear();
+        }
     }
 
     bool hasDeviceError = mDevice->hasDeviceError();
@@ -2189,25 +2456,121 @@
     mCameraServiceProxyWrapper->logClose(mCameraIdStr, closeLatencyMs, hasDeviceError);
 }
 
-/** Device-related methods */
+bool CameraDeviceClient::matchSharedStreamingRequest(int reqId) {
+    if (!mSharedMode) {
+        return false;
+    }
+    // In shared mode, check if the result req id matches the streaming request
+    // sent by client.
+    if (reqId == mSharedStreamingRequest.first) {
+        return true;
+    }
+    return false;
+}
+
+bool CameraDeviceClient::matchSharedCaptureRequest(int reqId) {
+    if (!mSharedMode) {
+        return false;
+    }
+    // In shared mode, only primary clients can send the capture request. If the
+    // result req id does not match the streaming request id, check against the
+    // capture request ids sent by the primary client.
+    if (mIsPrimaryClient) {
+        auto iter = mSharedRequestMap.find(reqId);
+        if (iter != mSharedRequestMap.end()) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void CameraDeviceClient::onResultAvailable(const CaptureResult& result) {
     ATRACE_CALL();
-    ALOGV("%s", __FUNCTION__);
+    ALOGV("%s E", __FUNCTION__);
+    CaptureResult mutableResult = result;
+    bool matchStreamingRequest, matchCaptureRequest, sharedStreamingLastFrame;
+    if (mSharedMode) {
+        int clientReqId;
+        matchStreamingRequest = matchSharedStreamingRequest(result.mResultExtras.requestId);
+        matchCaptureRequest = matchSharedCaptureRequest(result.mResultExtras.requestId);
+        if (matchStreamingRequest) {
+            clientReqId = mSharedStreamingRequest.second;
+            // When a client stops streaming using cancelRequest, we still need to deliver couple
+            // more capture results to the client, till the lastframe number returned by the
+            // cancelRequest. Therefore, only clean the shared streaming request once all the frames for
+            // the repeating request have been delivered to the client.
+            sharedStreamingLastFrame = (mStreamingRequestId == REQUEST_ID_NONE)
+                    && (result.mResultExtras.frameNumber >= mStreamingRequestLastFrameNumber);
+            if (sharedStreamingLastFrame) {
+                mSharedStreamingRequest.first = REQUEST_ID_NONE;
+                mSharedStreamingRequest.second = REQUEST_ID_NONE;
+            }
+        } else if (matchCaptureRequest) {
+            clientReqId = mSharedRequestMap[result.mResultExtras.requestId];
+            mSharedRequestMap.erase(result.mResultExtras.requestId);
+        } else {
+            return;
+        }
+        mutableResult.mResultExtras.requestId = clientReqId;
+        if (mutableResult.mMetadata.update(ANDROID_REQUEST_ID, &clientReqId, 1) != OK) {
+            ALOGE("%s Failed to set request ID in metadata.", __FUNCTION__);
+            return;
+        }
+    }
 
     // Thread-safe. No lock necessary.
     sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
     if (remoteCb != NULL) {
-        remoteCb->onResultReceived(result.mMetadata, result.mResultExtras,
-                result.mPhysicalMetadatas);
+        remoteCb->onResultReceived(mutableResult.mMetadata, mutableResult.mResultExtras,
+                mutableResult.mPhysicalMetadatas);
+        if (mSharedMode) {
+            // If all the capture requests for this client has been processed,
+            // send onDeviceidle callback.
+            if ((mSharedStreamingRequest.first == REQUEST_ID_NONE) && mSharedRequestMap.empty() ) {
+                markClientIdle();
+            }
+        }
     }
 
     // Access to the composite stream map must be synchronized
     Mutex::Autolock l(mCompositeLock);
     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
-        mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
+        mCompositeStreamMap.valueAt(i)->onResultAvailable(mutableResult);
     }
 }
 
+void CameraDeviceClient::markClientActive() {
+    Mutex::Autolock l(mDevice->mSharedDeviceActiveLock);
+    if (mDeviceActive) {
+        // Already in active state.
+        return;
+    }
+    status_t res = startCameraStreamingOps();
+    if (res != OK) {
+        ALOGE("%s: Camera %s: Error starting camera streaming ops: %d", __FUNCTION__,
+                mCameraIdStr.c_str(), res);
+    }
+    mDeviceActive = true;
+}
+
+void CameraDeviceClient::markClientIdle() {
+    Mutex::Autolock l(mDevice->mSharedDeviceActiveLock);
+    if (!mDeviceActive) {
+        // Already in idle state.
+        return;
+    }
+    sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
+    if (remoteCb != NULL) {
+        remoteCb->onDeviceIdle();
+    }
+    status_t res = finishCameraStreamingOps();
+    if (res != OK) {
+        ALOGE("%s: Camera %s: Error finishing streaming ops: %d", __FUNCTION__,
+                mCameraIdStr.c_str(), res);
+    }
+    mDeviceActive = false;
+}
+
 binder::Status CameraDeviceClient::checkPidStatus(const char* checkLocation) {
     if (mDisconnected) {
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 42f2752..a92b465 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -61,7 +61,8 @@
             int clientPid,
             uid_t clientUid,
             int servicePid,
-            int rotationOverride);
+            int rotationOverride,
+            bool sharedMode);
 
     sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
 };
@@ -95,6 +96,11 @@
     virtual binder::Status cancelRequest(int requestId,
             /*out*/
             int64_t* lastFrameNumber = NULL) override;
+    virtual binder::Status startStreaming(
+            const std::vector<int>& streamIds,
+            const std::vector<int>& surfaceIds,
+            /*out*/
+            hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
 
     virtual binder::Status beginConfigure() override;
 
@@ -175,6 +181,8 @@
             /*out*/
             sp<hardware::camera2::ICameraOfflineSession>* session) override;
 
+    virtual binder::Status isPrimaryClient(/*out*/bool* isPrimary) override;
+
     /**
      * Interface used by CameraService
      */
@@ -194,7 +202,8 @@
             int servicePid,
             bool overrideForPerfClass,
             int rotationOverride,
-            const std::string& originalCameraId);
+            const std::string& originalCameraId,
+            bool sharedMode);
     virtual ~CameraDeviceClient();
 
     virtual status_t      initialize(sp<CameraProviderManager> manager,
@@ -237,6 +246,7 @@
     virtual void notifyPrepared(int streamId);
     virtual void notifyRequestQueueEmpty();
     virtual void notifyRepeatingRequestError(long lastFrameNumber);
+    virtual void notifyClientSharedAccessPriorityChanged(bool primaryClient);
 
     void setImageDumpMask(int mask) { if (mDevice != nullptr) mDevice->setImageDumpMask(mask); }
     /**
@@ -315,6 +325,11 @@
             /*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
             /*out*/int32_t*  currentStreamId);
 
+    bool matchSharedStreamingRequest(int reqId);
+    bool matchSharedCaptureRequest(int reqId);
+    void markClientActive();
+    void markClientIdle();
+
     // IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
     KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
 
@@ -336,6 +351,9 @@
     // Streaming request ID
     int32_t mStreamingRequestId;
     Mutex mStreamingRequestIdLock;
+    std::pair<int32_t, int32_t> mSharedStreamingRequest;
+    std::map<int32_t, int32_t> mSharedRequestMap;
+    int64_t mStreamingRequestLastFrameNumber;
     static const int32_t REQUEST_ID_NONE = -1;
 
     int32_t mRequestIdCounter;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 9a1fdd6..9f85594 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -307,6 +307,9 @@
     }
 }
 
+void CameraOfflineSessionClient::notifyClientSharedAccessPriorityChanged(bool /*primaryClient*/) {
+}
+
 void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
         nsecs_t timestamp) {
 
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 77de874..9f441f3 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -52,7 +52,7 @@
             const std::string& clientPackageName,
             const std::optional<std::string>& clientFeatureId,
             const std::string& cameraIdStr, int cameraFacing, int sensorOrientation,
-            int clientPid, uid_t clientUid, int servicePid) :
+            int clientPid, uid_t clientUid, int servicePid, bool sharedMode) :
             CameraService::BasicClient(
                     cameraService,
                     IInterface::asBinder(remoteCallback),
@@ -60,7 +60,7 @@
                     // (v)ndk doesn't have offline session support
                     clientPackageName, /*overridePackageName*/false, clientFeatureId,
                     cameraIdStr, cameraFacing, sensorOrientation, clientPid, clientUid, servicePid,
-                    hardware::ICameraService::ROTATION_OVERRIDE_NONE),
+                    hardware::ICameraService::ROTATION_OVERRIDE_NONE, sharedMode),
             mRemoteCallback(remoteCallback), mOfflineSession(session),
             mCompositeStreamMap(offlineCompositeStreamMap) {}
 
@@ -123,6 +123,7 @@
     void notifyRepeatingRequestError(long lastFrameNumber) override;
     status_t injectCamera(const std::string& injectedCamId,
             sp<CameraProviderManager> manager) override;
+    void notifyClientSharedAccessPriorityChanged(bool primaryClient) override;
     status_t stopInjection() override;
     status_t injectSessionParams(
         const hardware::camera2::impl::CameraMetadataNative& sessionParams) override;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 352c6f8..ef0c387 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -31,6 +31,7 @@
 #include <camera/CameraSessionStats.h>
 #include <camera/StringUtils.h>
 #include <com_android_window_flags.h>
+#include <com_android_internal_camera_flags.h>
 
 #include "common/Camera2ClientBase.h"
 
@@ -39,12 +40,14 @@
 #include "device3/Camera3Device.h"
 #include "device3/aidl/AidlCamera3Device.h"
 #include "device3/hidl/HidlCamera3Device.h"
+#include "device3/aidl/AidlCamera3SharedDevice.h"
 
 namespace android {
 
 using namespace camera2;
 
 namespace wm_flags = com::android::window::flags;
+namespace flags = com::android::internal::camera::flags;
 
 // Interface used by CameraService
 
@@ -66,10 +69,11 @@
         int servicePid,
         bool overrideForPerfClass,
         int rotationOverride,
+        bool sharedMode,
         bool legacyClient):
         TClientBase(cameraService, remoteCallback, attributionAndPermissionUtils, clientPackageName,
                 systemNativeClient, clientFeatureId, cameraId, api1CameraId, cameraFacing,
-                sensorOrientation, clientPid, clientUid, servicePid, rotationOverride),
+                sensorOrientation, clientPid, clientUid, servicePid, rotationOverride, sharedMode),
         mSharedCameraCallbacks(remoteCallback),
         mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
         mDeviceActive(false), mApi1CameraId(api1CameraId)
@@ -124,12 +128,19 @@
                             TClientBase::mRotationOverride, mLegacyClient);
             break;
         case IPCTransport::AIDL:
-            mDevice =
+            if (TClientBase::mSharedMode) {
+                mDevice = AidlCamera3SharedDevice::getInstance(mCameraServiceProxyWrapper,
+                            TClientBase::mAttributionAndPermissionUtils,
+                            TClientBase::mCameraIdStr, mOverrideForPerfClass,
+                            TClientBase::mRotationOverride, mLegacyClient);
+            } else {
+                mDevice =
                     new AidlCamera3Device(mCameraServiceProxyWrapper,
                             TClientBase::mAttributionAndPermissionUtils,
                             TClientBase::mCameraIdStr, mOverrideForPerfClass,
                             TClientBase::mRotationOverride, mLegacyClient);
-             break;
+            }
+            break;
         default:
             ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
                     TClientBase::mCameraIdStr.c_str());
@@ -171,9 +182,10 @@
 Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
     ATRACE_CALL();
 
-    TClientBase::mDestructionStarted = true;
-
-    disconnect();
+    if (!TClientBase::mDisconnected) {
+        TClientBase::mDestructionStarted = true;
+        disconnect();
+    }
 
     ALOGI("%s: Client object's dtor for Camera Id %s completed. Client was: %s (PID %d, UID %u)",
             __FUNCTION__, TClientBase::mCameraIdStr.c_str(),
@@ -261,7 +273,10 @@
 template <typename TClientBase>
 binder::Status Camera2ClientBase<TClientBase>::disconnect() {
 
-    return disconnectImpl();
+   if ( !TClientBase::mDisconnected) {
+       return disconnectImpl();
+   }
+   return binder::Status::ok();
 }
 
 template <typename TClientBase>
@@ -299,7 +314,11 @@
 template <typename TClientBase>
 void Camera2ClientBase<TClientBase>::detachDevice() {
     if (mDevice == 0) return;
-    mDevice->disconnect();
+    if (TClientBase::mSharedMode) {
+        mDevice->disconnectClient(TClientBase::getClientPid());
+    } else {
+        mDevice->disconnect();
+    }
 
     ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.c_str());
 }
@@ -342,6 +361,12 @@
 }
 
 template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyClientSharedAccessPriorityChanged(bool primaryClient) {
+    ALOGV("%s Camera %s access priorities changed for client %d primaryClient=%d", __FUNCTION__,
+            TClientBase::mCameraIdStr.c_str(), TClientBase::getClientUid(), primaryClient);
+}
+
+template <typename TClientBase>
 void Camera2ClientBase<TClientBase>::notifyPhysicalCameraChange(const std::string &physicalId) {
     using android::hardware::ICameraService;
     // We're only interested in this notification if rotationOverride is turned on.
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index c9d5735..a825754 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -65,6 +65,7 @@
                       int servicePid,
                       bool overrideForPerfClass,
                       int rotationOverride,
+                      bool sharedMode,
                       bool legacyClient = false);
     virtual ~Camera2ClientBase();
 
@@ -97,6 +98,7 @@
     virtual void          notifyPrepared(int streamId);
     virtual void          notifyRequestQueueEmpty();
     virtual void          notifyRepeatingRequestError(long lastFrameNumber);
+    virtual void          notifyClientSharedAccessPriorityChanged(bool primaryClient) override;
 
     void                  notifyIdleWithUserTag(int64_t requestCount, int64_t resultErrorCount,
                                      bool deviceError,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 9c8f5ad..9b76426 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -34,6 +34,7 @@
 #include "device3/Camera3StreamInterface.h"
 #include "device3/StatusTracker.h"
 #include "binder/Status.h"
+#include "FrameProcessorBase.h"
 #include "FrameProducer.h"
 #include "utils/IPCTransport.h"
 #include "utils/SessionConfigurationUtils.h"
@@ -92,6 +93,7 @@
     virtual status_t initialize(sp<CameraProviderManager> manager,
             const std::string& monitorTags) = 0;
     virtual status_t disconnect() = 0;
+    virtual status_t disconnectClient(int) {return OK;};
 
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
     virtual status_t startWatchingTags(const std::string &tags) = 0;
@@ -286,6 +288,75 @@
      */
     virtual status_t deleteStream(int id) = 0;
 
+
+    /**
+     * This function is responsible for configuring camera streams at the start of a session.
+     * In shared session mode, where multiple clients may access the camera, camera service
+     * applies a predetermined shared session configuration. If the camera is opened in non-shared
+     * mode, this function is a no-op.
+     */
+    virtual status_t beginConfigure() = 0;
+
+    /**
+     * In shared session mode, this function retrieves the stream IDs associated with a specific
+     * output configuration.
+     */
+    virtual status_t getSharedStreamIds(const android::camera3::OutputStreamInfo &config,
+            std::vector<int>& streamIds) = 0;
+
+    /**
+     * In shared session mode, this function add surfaces to an existing shared stream ID.
+     */
+    virtual status_t addSharedSurfaces(int streamId,
+            const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+            const std::vector<sp<Surface>>& surfaces, std::vector<int> *surfaceIds = nullptr) = 0;
+
+    /**
+     * In shared session mode, this function remove surfaces from an existing shared stream ID.
+     */
+    virtual status_t removeSharedSurfaces(int streamId, const std::vector<size_t> &surfaceIds) = 0;
+
+    /**
+     * In shared session mode, this function retrieves the frame processor.
+     */
+    virtual sp<camera2::FrameProcessorBase> getSharedFrameProcessor() = 0;
+
+    /**
+     * Submit a shared streaming request for streaming.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
+     */
+    virtual status_t setSharedStreamingRequest(
+            const PhysicalCameraSettingsList &request,
+            const SurfaceMap &surfaceMap, int32_t *sharedReqID,
+            int64_t *lastFrameNumber = NULL) = 0;
+
+    /**
+     * Clear the shared streaming request slot.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
+     */
+    virtual status_t clearSharedStreamingRequest(int64_t *lastFrameNumber = NULL) = 0;
+
+    /**
+     * In shared session mode, only primary clients can change the capture
+     * parameters through capture request or repeating request. When the primary
+     * client sends the capture request to the camera device, the request ID is
+     * overridden by the camera device to maintain unique ID. This API is
+     * similar to captureList API, with only difference that the request ID is
+     * changed by the device before submitting the request to HAL.
+     * Output sharedReqID is the request ID actually used.
+     * Output lastFrameNumber is the expected last frame number of the list of requests.
+     */
+    virtual status_t setSharedCaptureRequest(const PhysicalCameraSettingsList &request,
+                                 const SurfaceMap &surfaceMap, int32_t *sharedReqID,
+                                 int64_t *lastFrameNumber = NULL) = 0;
+
+    /**
+     * Submit a start streaming request.
+     * Output lastFrameNumber is the last frame number of the previous streaming request.
+     */
+    virtual status_t startStreaming(const int32_t reqId, const SurfaceMap &surfaceMap,
+            int32_t *sharedReqID, int64_t *lastFrameNumber = NULL) = 0;
+
     /**
      * Take the currently-defined set of streams and configure the HAL to use
      * them. This is a long-running operation (may be several hundered ms).
@@ -519,6 +590,9 @@
     virtual status_t injectSessionParams(
         const CameraMetadata& sessionParams) = 0;
 
+    // Lock to synchronize onDeviceActive and onDeviceIdle callbacks when camera
+    // has been opened in shared mode.
+    mutable Mutex mSharedDeviceActiveLock;
 protected:
     bool mImageDumpMask = 0;
     std::vector<int64_t> mStreamUseCaseOverrides;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 51f06cb..54a7ec9 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -22,6 +22,8 @@
 
 #include "CameraProviderManager.h"
 
+#include "config/SharedSessionConfigReader.h"
+
 #include <aidl/android/hardware/camera/device/ICameraDevice.h>
 
 #include <algorithm>
@@ -62,6 +64,7 @@
 using namespace camera3::SessionConfigurationUtils;
 using std::literals::chrono_literals::operator""s;
 using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera2::params::OutputConfiguration;
 
 namespace flags = com::android::internal::camera::flags;
 namespace vd_flags = android::companion::virtualdevice::flags;
@@ -1853,6 +1856,84 @@
     return res;
 }
 
+bool CameraProviderManager::ProviderInfo::DeviceInfo3::isAutomotiveDevice() {
+    // Checks the property ro.hardware.type and returns true if it is
+    // automotive.
+    char value[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.hardware.type", value, "");
+    return strncmp(value, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addSharedSessionConfigurationTags(
+        const std::string &cameraId) {
+    status_t res = OK;
+    {
+        SharedSessionConfigReader configReader;
+        ErrorCode status =
+                configReader.parseSharedSessionConfig(
+                                    (std::string(SHARED_SESSION_FILE_PATH)
+                                     + std::string(SHARED_SESSION_FILE_NAME)).c_str());
+        if (status != 0) {
+            ALOGE("%s: failed to initialize SharedSessionConfigReader with ErrorCode %s",
+                  __FUNCTION__, SharedSessionConfigUtils::toString(status));
+            return BAD_VALUE;
+        }
+        const int32_t sharedColorSpaceTag = ANDROID_SHARED_SESSION_COLOR_SPACE;
+        const int32_t sharedOutputConfigurationsTag = ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS;
+        auto& c = mCameraCharacteristics;
+        int32_t colorSpace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED;
+
+        status = configReader.getColorSpace(&colorSpace);
+        if (status != 0) {
+            ALOGE("%s: failed to get color space from config reader with ErrorCode %s",
+                  __FUNCTION__, SharedSessionConfigUtils::toString(status));
+            return BAD_VALUE;
+        }
+
+        res = c.update(sharedColorSpaceTag, &colorSpace, 1);
+        if (res != OK) {
+            ALOGE("%s: failed to update sharedColorSpaceTag with error %d", __FUNCTION__, res);
+            return res;
+        }
+
+        std::vector<SharedSessionConfigReader::SharedSessionConfig> outputConfigurations;
+        status = configReader.getAvailableSharedSessionConfigs(cameraId.c_str(),
+                                                               &outputConfigurations);
+        if (status != 0) {
+            ALOGE("%s: failed to get output configurations from config reader with ErrorCode %s",
+                  __FUNCTION__, SharedSessionConfigUtils::toString(status));
+            return BAD_VALUE;
+        }
+
+        std::vector<int64_t> sharedOutputConfigEntries;
+
+        for (auto outputConfig : outputConfigurations) {
+            sharedOutputConfigEntries.push_back(outputConfig.surfaceType);
+            sharedOutputConfigEntries.push_back(outputConfig.width);
+            sharedOutputConfigEntries.push_back(outputConfig.height);
+            sharedOutputConfigEntries.push_back(outputConfig.format);
+            sharedOutputConfigEntries.push_back(outputConfig.mirrorMode);
+            sharedOutputConfigEntries.push_back(outputConfig.useReadoutTimestamp);
+            sharedOutputConfigEntries.push_back(outputConfig.timestampBase);
+            sharedOutputConfigEntries.push_back(outputConfig.dataSpace);
+            sharedOutputConfigEntries.push_back(outputConfig.usage);
+            sharedOutputConfigEntries.push_back(outputConfig.streamUseCase);
+            if (strcmp(outputConfig.physicalCameraId.c_str(), "")) {
+                sharedOutputConfigEntries.push_back(outputConfig.physicalCameraId.length());
+                for (char c : outputConfig.physicalCameraId) {
+                    sharedOutputConfigEntries.push_back(c);
+                }
+            } else {
+                sharedOutputConfigEntries.push_back(/* physical camera id len */ 0);
+            }
+        }
+
+        res = c.update(sharedOutputConfigurationsTag, sharedOutputConfigEntries.data(),
+                       sharedOutputConfigEntries.size());
+    }
+    return res;
+}
+
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::removeAvailableKeys(
         CameraMetadata& c, const std::vector<uint32_t>& keys, uint32_t keyTag) {
     status_t res = OK;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index b686a58..3092d58 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -44,6 +44,8 @@
 #include <binder/IServiceManager.h>
 #include <camera/VendorTagDescriptor.h>
 
+#include "config/SharedSessionConfigUtils.h"
+
 namespace android {
 
 using hardware::camera2::utils::CameraIdAndSessionConfiguration;
@@ -762,6 +764,8 @@
             status_t addPreCorrectionActiveArraySize();
             status_t addReadoutTimestampTag(bool readoutTimestampSupported = true);
             status_t addSessionConfigQueryVersionTag();
+            status_t addSharedSessionConfigurationTags(const std::string &cameraId);
+            bool isAutomotiveDevice();
 
             static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
                     android_pixel_format_t format,
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 4bfe11d..a51f156 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -30,6 +30,8 @@
 
 #include "device3/DistortionMapper.h"
 #include "device3/ZoomRatioMapper.h"
+#include <filesystem>
+#include <utils/AttributionAndPermissionUtils.h>
 #include <utils/SessionConfigurationUtils.h>
 #include <utils/Trace.h>
 
@@ -694,6 +696,13 @@
                 {ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, ANDROID_CONTROL_AE_TARGET_FPS_RANGE});
     }
 
+    std::filesystem::path sharedSessionConfigFilePath =
+            std::string(SHARED_SESSION_FILE_PATH) + std::string(SHARED_SESSION_FILE_NAME);
+    if (std::filesystem::exists(sharedSessionConfigFilePath)
+            && mSystemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+        addSharedSessionConfigurationTags(id);
+    }
+
     if (!kEnableLazyHal) {
         // Save HAL reference indefinitely
         mSavedInterface = interface;
diff --git a/services/camera/libcameraservice/config/SharedSessionConfigReader.cpp b/services/camera/libcameraservice/config/SharedSessionConfigReader.cpp
new file mode 100644
index 0000000..2ea5ffa
--- /dev/null
+++ b/services/camera/libcameraservice/config/SharedSessionConfigReader.cpp
@@ -0,0 +1,239 @@
+//
+// Copyright 2024 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 "SharedSessionConfigReader"
+
+#include "SharedSessionConfigReader.h"
+
+#include <fstream>
+#include <utils/Log.h>
+
+using tinyxml2::XML_SUCCESS;
+using tinyxml2::XMLDocument;
+namespace android {
+
+ErrorCode SharedSessionConfigReader::parseSharedSessionConfig(
+        const char* sharedSessionConfigFilePath) {
+    if (!mCameraIdToSharedSessionConfigs.empty()) {
+        ALOGV("mCameraIdToSharedSessionConfigs already initialized.");
+        return ErrorCode::STATUS_OK;
+    }
+
+    XMLDocument xmlDoc;
+
+    // load and parse the configuration file
+    xmlDoc.LoadFile(sharedSessionConfigFilePath);
+    if (xmlDoc.ErrorID() != XML_SUCCESS) {
+        ALOGE("%s: Failed to load/parse the configuration file: %s, with error: %s", __FUNCTION__,
+              sharedSessionConfigFilePath, xmlDoc.ErrorStr());
+        return ErrorCode::ERROR_READ_CONFIG_FILE;
+    }
+
+    ErrorCode status = parseSharedSessionConfigFromXMLDocument(xmlDoc);
+    if (status != ErrorCode::STATUS_OK) {
+        ALOGE("%s: Error while parsing XML elements of file at: %s", __FUNCTION__,
+              sharedSessionConfigFilePath);
+        return status;
+    }
+
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigReader::parseSharedSessionConfigFromXMLDocument(
+        const XMLDocument& xmlDoc) {
+    const XMLElement* rootElem = xmlDoc.RootElement();
+    if (strcmp(rootElem->Name(), "SharedCameraSessionConfigurations")) {
+        ALOGE("%s: Expected root element to be 'SharedCameraSessionConfigurations'. Instead got %s",
+              __FUNCTION__, rootElem->Name());
+        return ErrorCode::ERROR_READ_CONFIG_FILE;
+    }
+
+    ErrorCode status;
+    const char* colorSpaceStr = rootElem->Attribute("colorSpace");
+    status = SharedSessionConfigUtils::getColorSpaceFromStr(colorSpaceStr, &mColorSpace);
+    if (status != ErrorCode::STATUS_OK) {
+        ALOGE("%s: getColorSpaceFromStr has returned an error: %s", __FUNCTION__,
+              SharedSessionConfigUtils::toString(status));
+        return status;
+    }
+
+    std::unordered_map<std::string, std::vector<SharedSessionConfig>>
+            cameraIdToSharedSessionConfigs;
+
+    for (const XMLElement* sharedConfigElem =
+                 rootElem->FirstChildElement("SharedCameraSessionConfiguration");
+            sharedConfigElem != nullptr;
+            sharedConfigElem =
+                 sharedConfigElem->NextSiblingElement("SharedCameraSessionConfiguration")) {
+
+        const char* cameraId = sharedConfigElem->Attribute("cameraId");
+        if (cameraId == nullptr || !strcmp(cameraId, "")) {
+            ALOGE("%s: cameraId attribute is empty", __FUNCTION__);
+            return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+        }
+
+        for (const XMLElement* outputConfigElem =
+                     sharedConfigElem->FirstChildElement("OutputConfiguration");
+                outputConfigElem != nullptr;
+                outputConfigElem = outputConfigElem->NextSiblingElement("OutputConfiguration")) {
+            int64_t surfaceType;
+            const XMLElement* surfaceTypeXml = outputConfigElem->FirstChildElement("surfaceType");
+            status = SharedSessionConfigUtils::getSurfaceTypeFromXml(surfaceTypeXml, &surfaceType);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getSurfaceTypeFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t width;
+            const XMLElement* widthXml = outputConfigElem->FirstChildElement("width");
+            status = SharedSessionConfigUtils::getWidthFromXml(widthXml, &width);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getWidthFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t height;
+            const XMLElement* heightXml = outputConfigElem->FirstChildElement("height");
+            status = SharedSessionConfigUtils::getHeightFromXml(heightXml, &height);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getHeightFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            std::string physicalCameraId;
+            const XMLElement* physicalCameraIdXml =
+                    outputConfigElem->FirstChildElement("physicalCameraId");
+            status = SharedSessionConfigUtils::getPhysicalCameraIdFromXml(physicalCameraIdXml,
+                                                                          &physicalCameraId);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getPhysicalCameraIdFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t streamUseCase;
+            const XMLElement* streamUseCaseXml =
+                    outputConfigElem->FirstChildElement("streamUseCase");
+            status = SharedSessionConfigUtils::getStreamUseCaseFromXml(streamUseCaseXml,
+                                                                       &streamUseCase);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getStreamUseCaseFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t timestampBase;
+            const XMLElement* timestampBaseXml =
+                    outputConfigElem->FirstChildElement("timestampBase");
+            status = SharedSessionConfigUtils::getTimestampBaseFromXml(timestampBaseXml,
+                                                                       &timestampBase);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getTimestampBaseFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t mirrorMode;
+            const XMLElement* mirrorModeXml = outputConfigElem->FirstChildElement("mirrorMode");
+            status = SharedSessionConfigUtils::getMirrorModeFromXml(mirrorModeXml, &mirrorMode);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getMirrorModeFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            bool useReadoutTimestamp;
+            const XMLElement* useReadoutTimestampXml =
+                    outputConfigElem->FirstChildElement("useReadoutTimestamp");
+            status = SharedSessionConfigUtils::getUseReadoutTimestampFromXml(useReadoutTimestampXml,
+                                                                             &useReadoutTimestamp);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getUseReadoutTimestampFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t format;
+            const XMLElement* formatXml = outputConfigElem->FirstChildElement("format");
+            status = SharedSessionConfigUtils::getFormatFromXml(formatXml, &format, surfaceType);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getFormatFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t usage;
+            const XMLElement* usageXml = outputConfigElem->FirstChildElement("usage");
+            status = SharedSessionConfigUtils::getUsageFromXml(usageXml, &usage, surfaceType);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getUsageFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            int64_t dataSpace;
+            const XMLElement* dataSpaceXml = outputConfigElem->FirstChildElement("dataSpace");
+            status = SharedSessionConfigUtils::getDataSpaceFromXml(dataSpaceXml, &dataSpace);
+            if (status != ErrorCode::STATUS_OK) {
+                ALOGE("%s: getUsageFromXml has returned an error: %s", __FUNCTION__,
+                      SharedSessionConfigUtils::toString(status));
+                return status;
+            }
+
+            cameraIdToSharedSessionConfigs[cameraId].push_back(
+                    SharedSessionConfig{surfaceType, width, height, physicalCameraId, streamUseCase,
+                                        timestampBase, mirrorMode, useReadoutTimestamp, format,
+                                        usage, dataSpace});
+        }
+    }
+
+    if (cameraIdToSharedSessionConfigs.empty()) {
+        ALOGE("%s: No elements with tag 'SharedCameraSessionConfiguration' in file", __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    mCameraIdToSharedSessionConfigs = cameraIdToSharedSessionConfigs;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigReader::getColorSpace(/* out */ int32_t* colorSpace) {
+    *colorSpace = mColorSpace;
+    return ErrorCode::STATUS_OK;
+}
+
+// Returns the cameraConfig parameters.
+ErrorCode SharedSessionConfigReader::getAvailableSharedSessionConfigs(
+        const char* cameraId, /* out */ std::vector<SharedSessionConfig>* availableConfigurations) {
+    if (mCameraIdToSharedSessionConfigs.empty()) {
+        ALOGE("%s: mCameraIdToSharedSessionConfigs is empty. Call initialize() first.",
+              __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_READER_UNINITIALIZED;
+    }
+
+    if (!mCameraIdToSharedSessionConfigs.contains(cameraId)) {
+        ALOGE("%s: cameraId: %s not found in mCameraIdToSharedSessionConfigs.", __FUNCTION__,
+              cameraId);
+        return ErrorCode::ERROR_BAD_PARAMETER;
+    }
+
+    *availableConfigurations = mCameraIdToSharedSessionConfigs[cameraId];
+    return ErrorCode::STATUS_OK;
+}
+
+}  // namespace android
diff --git a/services/camera/libcameraservice/config/SharedSessionConfigReader.h b/services/camera/libcameraservice/config/SharedSessionConfigReader.h
new file mode 100644
index 0000000..aa52236
--- /dev/null
+++ b/services/camera/libcameraservice/config/SharedSessionConfigReader.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 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_CAMERA_SHAREDSESSIONCONFIGREADER_H_
+#define ANDROID_SERVERS_CAMERA_SHAREDSESSIONCONFIGREADER_H_
+
+#include "SharedSessionConfigUtils.h"
+
+#include <string>
+#include "tinyxml2.h"
+#include <vector>
+#include <unordered_map>
+
+using tinyxml2::XMLDocument;
+using tinyxml2::XMLElement;
+namespace android {
+
+class SharedSessionConfigReader {
+public:
+
+    // Struct for shared session configurations.
+    struct SharedSessionConfig {
+        // TODO: add documentation for each field.
+        int64_t surfaceType;
+        int64_t width;
+        int64_t height;
+        std::string physicalCameraId;
+        int64_t streamUseCase;
+        int64_t timestampBase;
+        int64_t mirrorMode;
+        bool useReadoutTimestamp;
+        int64_t format;
+        int64_t usage;
+        int64_t dataSpace;
+    };
+
+    // Reads shared session config files and stores parsed results in mColorSpace and
+    // mCameraIdToSharedSessionConfigs.
+    ErrorCode parseSharedSessionConfig(const char* sharedSessionConfigFilePath);
+
+    // Reads shared session config files and stores parsed results in mColorSpace and
+    // mCameraIdToSharedSessionConfigs.
+    ErrorCode parseSharedSessionConfigFromXMLDocument(const XMLDocument& xmlDoc);
+
+    // Return color space of a camera device.
+    ErrorCode getColorSpace(int32_t* colorSpace);
+
+    // Return all available shared configs for a cameraId.
+    ErrorCode getAvailableSharedSessionConfigs(
+            const char* cameraId, std::vector<SharedSessionConfig>* availableConfigurations);
+
+private:
+
+    // shared color space of devices
+    int32_t mColorSpace;
+
+    // stores parsed configs, mapped from cameraId to available session configs.
+    std::unordered_map<std::string, std::vector<SharedSessionConfig>>
+            mCameraIdToSharedSessionConfigs;
+
+    // processes xml and populates mCameraIdToColorSpace and mCameraIdToSharedSessionConfigs. Called
+    // by initialize().
+    ErrorCode readConfig(const XMLElement* rootElem);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_SERVERS_CAMERA_SHAREDSESSIONCONFIGREADER_H_
diff --git a/services/camera/libcameraservice/config/SharedSessionConfigUtils.cpp b/services/camera/libcameraservice/config/SharedSessionConfigUtils.cpp
new file mode 100644
index 0000000..a9ccdc9
--- /dev/null
+++ b/services/camera/libcameraservice/config/SharedSessionConfigUtils.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2024 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 "SharedSessionConfigUtils"
+
+#include "SharedSessionConfigUtils.h"
+
+#include <inttypes.h>
+#include <sstream>
+#include <utils/Log.h>
+
+namespace android {
+
+const char* SharedSessionConfigUtils::toString(ErrorCode errorCode) {
+    switch (errorCode) {
+        case ErrorCode::STATUS_OK:
+            return "STATUS_OK";
+        case ErrorCode::ERROR_READ_CONFIG_FILE:
+            return "ERROR_READ_CONFIG_FILE";
+        case ErrorCode::ERROR_CONFIG_FILE_FORMAT:
+            return "ERROR_CONFIG_FILE_FORMAT";
+        case ErrorCode::ERROR_CONFIG_READER_UNINITIALIZED:
+            return "ERROR_CONFIG_READER_UNINITIALIZED";
+        case ErrorCode::ERROR_BAD_PARAMETER:
+            return "ERROR_BAD_PARAMETER";
+        default:
+            ALOGE("%s: Called toString on an unknown ErrorCode. This should never happen",
+                  __FUNCTION__);
+            return "";
+    }
+}
+
+ErrorCode SharedSessionConfigUtils::getColorSpaceFromStr(const char* colorSpaceStr,
+                                                         /* out */ int32_t* colorSpace) {
+    if (colorSpaceStr == nullptr || !strcmp(colorSpaceStr, "")) {
+        *colorSpace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED;
+        return ErrorCode::STATUS_OK;
+    }
+
+    int32_t colorSpaceInt = (int32_t) std::strtol(colorSpaceStr, nullptr, 0);
+    if (VALID_COLOR_SPACES.find(colorSpaceInt) == VALID_COLOR_SPACES.end()) {
+        ALOGE("%s: colorSpace %" PRId32 " is invalid: ", __FUNCTION__, colorSpaceInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_COLOR_SPACES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *colorSpace = colorSpaceInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getSurfaceTypeFromXml(const XMLElement* surfaceTypeXml,
+                                                          /* out */ int64_t* surfaceType) {
+    if (surfaceTypeXml == nullptr || surfaceTypeXml->GetText() == nullptr
+            || !strcmp(surfaceTypeXml->GetText(), "")) {
+        ALOGE("%s: surface type field must be populated", __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    int64_t surfaceTypeInt = std::strtol(surfaceTypeXml->GetText(), nullptr, 0);
+    if (VALID_SURFACE_TYPES.find(surfaceTypeInt) == VALID_SURFACE_TYPES.end()) {
+        ALOGE("%s: surfaceType %" PRId64 " is invalid: ", __FUNCTION__, surfaceTypeInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_SURFACE_TYPES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *surfaceType = surfaceTypeInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getWidthFromXml(const XMLElement* widthXml,
+                                                    /* out */ int64_t* width) {
+    if (widthXml == nullptr || widthXml->GetText() == nullptr
+            || !strcmp(widthXml->GetText(), "")) {
+        ALOGE("%s: width field must be populated", __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    const char* widthStr = widthXml->GetText();
+    *width = std::strtol(widthStr, nullptr, 0);
+    if (*width <= 0) {
+        ALOGE("%s: width value is invalid", __FUNCTION__);
+    }
+
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getHeightFromXml(const XMLElement* heightXml,
+                                                     /* out */ int64_t* height) {
+    if (heightXml == nullptr || heightXml->GetText() == nullptr
+            || !strcmp(heightXml->GetText(), "")) {
+        ALOGE("%s: height field must be populated", __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    const char* heightStr = heightXml->GetText();
+    *height = std::strtol(heightStr, nullptr, 0);
+    if (*height <= 0) {
+        ALOGE("%s: height value is invalid", __FUNCTION__);
+    }
+
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getPhysicalCameraIdFromXml(
+        const XMLElement* physicalCameraIdXml, /* out */ std::string* physicalCameraId) {
+    *physicalCameraId =
+            (physicalCameraIdXml == nullptr || physicalCameraIdXml->GetText() == nullptr)
+                    ? "": physicalCameraIdXml->GetText();
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getStreamUseCaseFromXml(const XMLElement* streamUseCaseXml,
+                                                            /* out */ int64_t* streamUseCase) {
+    if (streamUseCaseXml == nullptr || streamUseCaseXml->GetText() == nullptr
+            || !strcmp(streamUseCaseXml->GetText(), "")) {
+        *streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
+        return ErrorCode::STATUS_OK;
+    }
+
+    int64_t streamUseCaseInt = std::strtol(streamUseCaseXml->GetText(), nullptr, 0);
+    if (VALID_STREAM_USE_CASES.find(streamUseCaseInt) == VALID_STREAM_USE_CASES.end()) {
+        ALOGE("%s: streamUseCase %" PRId64 " is invalid: ", __FUNCTION__, streamUseCaseInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_STREAM_USE_CASES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *streamUseCase = streamUseCaseInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getTimestampBaseFromXml(const XMLElement* timestampBaseXml,
+                                                            /* out */ int64_t* timestampBase) {
+    if (timestampBaseXml == nullptr || timestampBaseXml->GetText() == nullptr
+            || !strcmp(timestampBaseXml->GetText(), "")) {
+        *timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT;
+        return ErrorCode::STATUS_OK;
+    }
+
+    int64_t timestampBaseInt = std::strtol(timestampBaseXml->GetText(), nullptr, 0);
+    if (VALID_TIMESTAMP_BASES.find(timestampBaseInt) == VALID_TIMESTAMP_BASES.end()) {
+        ALOGE("%s: timestampBase %" PRId64 " is invalid: ", __FUNCTION__, timestampBaseInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_TIMESTAMP_BASES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *timestampBase = timestampBaseInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getMirrorModeFromXml(const XMLElement* mirrorModeXml,
+                                                         /* out */ int64_t* mirrorMode) {
+    if (mirrorModeXml == nullptr || mirrorModeXml->GetText() == nullptr
+            || !strcmp(mirrorModeXml->GetText(), "")) {
+        *mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO;
+        return ErrorCode::STATUS_OK;
+    }
+
+    int64_t mirrorModeInt = std::strtol(mirrorModeXml->GetText(), nullptr, 0);
+    if (VALID_MIRROR_MODES.find(mirrorModeInt) == VALID_MIRROR_MODES.end()) {
+        ALOGE("%s: mirrorMode %" PRId64 " is invalid: ", __FUNCTION__, mirrorModeInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_MIRROR_MODES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *mirrorMode = mirrorModeInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getUseReadoutTimestampFromXml(
+        const XMLElement* useReadoutTimestampXml, /* out */ bool* useReadoutTimestamp) {
+    if (useReadoutTimestampXml != nullptr && useReadoutTimestampXml->GetText() != nullptr
+            && strcmp(useReadoutTimestampXml->GetText(), "")) {
+        const char* useReadoutTimestampStr = useReadoutTimestampXml->GetText();
+        if (!strcmp(useReadoutTimestampStr, "1")) {
+            *useReadoutTimestamp = true;
+            return ErrorCode::STATUS_OK;
+        } else if (strcmp(useReadoutTimestampStr, "0")) {
+            ALOGE("%s: useReadoutTimestamp string %s is invalid: ", __FUNCTION__,
+                  useReadoutTimestampStr);
+            ALOGE("%s: Expected one of: {0, 1}", __FUNCTION__);
+            return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+        }
+    }
+
+    *useReadoutTimestamp = false;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getFormatFromXml(const XMLElement* formatXml,
+                                                     /* out */ int64_t* format,
+                                                     int64_t surfaceType) {
+    if (surfaceType != OutputConfiguration::SURFACE_TYPE_IMAGE_READER) {
+        // if surface type is not image reader, format must default to impl defined enum.
+        *format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+        return ErrorCode::STATUS_OK;
+    }
+
+    if (formatXml == nullptr || formatXml->GetText() == nullptr
+            || !strcmp(formatXml->GetText(), "")) {
+        ALOGE("%s: format field must be populated", __FUNCTION__);
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    int64_t formatInt = std::strtol(formatXml->GetText(), nullptr, 0);
+    if (VALID_FORMATS.find(formatInt) == VALID_FORMATS.end()) {
+        ALOGE("%s: format %" PRId64 " is invalid: ", __FUNCTION__, formatInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_FORMATS).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *format = formatInt;
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getUsageFromXml(const XMLElement* usageXml,
+                                                    /* out */ int64_t* usage,
+                                                    int64_t surfaceType) {
+    if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE) {
+        // if surface type is SURFACE_TYPE_SURFACE_TEXTURE, usage must default to
+        // AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE.
+        *usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+        return ErrorCode::STATUS_OK;
+    }
+
+    if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
+        // if surface type is SURFACE_TYPE_SURFACE_VIEW, usage must default to
+        // AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY.
+        *usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
+        return ErrorCode::STATUS_OK;
+    }
+
+    if (surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER
+            || surfaceType == OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC) {
+        // if surface type is SURFACE_TYPE_MEDIA_RECORDER or SURFACE_TYPE_MEDIA_CODEC, usage must
+        // default to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE
+        *usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
+        return ErrorCode::STATUS_OK;
+    }
+
+    if (usageXml == nullptr || usageXml->GetText() == nullptr
+            || !strcmp(usageXml->GetText(), "")) {
+        *usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER;
+        return ErrorCode::STATUS_OK;
+    }
+
+    const char* usageStr = usageXml->GetText();
+    std::vector<std::string> usageFlags = splitString(usageStr, '|');
+
+    for (std::string usageFlagStr : usageFlags) {
+        int64_t usageFlag = std::strtol(usageFlagStr.c_str(), nullptr, 0);
+        if (VALID_USAGES.find(usageFlag) == VALID_USAGES.end()) {
+            ALOGE("%s: usage %" PRId64 " is invalid: ", __FUNCTION__, usageFlag);
+            ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_USAGES).c_str());
+            return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+        }
+
+        *usage |= usageFlag;
+    }
+
+    return ErrorCode::STATUS_OK;
+}
+
+ErrorCode SharedSessionConfigUtils::getDataSpaceFromXml(const XMLElement* dataSpaceXml,
+                                                        /* out */ int64_t* dataSpace) {
+    if (dataSpaceXml == nullptr || dataSpaceXml->GetText() == nullptr
+            || !strcmp(dataSpaceXml->GetText(), "")) {
+        *dataSpace = HAL_DATASPACE_UNKNOWN;
+        return ErrorCode::STATUS_OK;
+    }
+
+    int64_t dataSpaceInt = std::strtol(dataSpaceXml->GetText(), nullptr, 0);
+    if (VALID_DATA_SPACES.find(dataSpaceInt) == VALID_DATA_SPACES.end()) {
+        ALOGE("%s: dataSpace %" PRId64 " is invalid: ", __FUNCTION__, dataSpaceInt);
+        ALOGE("%s: Expected one of: %s", __FUNCTION__, setToString(VALID_DATA_SPACES).c_str());
+        return ErrorCode::ERROR_CONFIG_FILE_FORMAT;
+    }
+
+    *dataSpace = dataSpaceInt;
+    return ErrorCode::STATUS_OK;
+}
+
+std::vector<std::string> SharedSessionConfigUtils::splitString(std::string inputString,
+                                                               char delimiter) {
+    std::vector<std::string> tokens;
+    std::istringstream iss(inputString);
+    std::string token;
+
+    while (std::getline(iss, token, delimiter)) {
+        tokens.push_back(token);
+    }
+
+    return tokens;
+}
+
+std::string SharedSessionConfigUtils::setToString(const std::set<int64_t>& s) {
+    std::ostringstream oss;
+    oss << "{";
+
+    for (auto it = s.begin(); it != s.end();) {
+        oss << *it;
+
+        if (++it != s.end()) {
+            oss << ", ";
+        }
+    }
+
+    oss << "}";
+    return oss.str();
+}
+
+}  // namespace android
diff --git a/services/camera/libcameraservice/config/SharedSessionConfigUtils.h b/services/camera/libcameraservice/config/SharedSessionConfigUtils.h
new file mode 100644
index 0000000..2efe1dd
--- /dev/null
+++ b/services/camera/libcameraservice/config/SharedSessionConfigUtils.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2024 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_CAMERA_SHAREDSESSIONCONFIGUTILS_H_
+#define ANDROID_SERVERS_CAMERA_SHAREDSESSIONCONFIGUTILS_H_
+
+#define SHARED_SESSION_FILE_PATH "system_ext/etc/"
+#define SHARED_SESSION_FILE_NAME "shared_session_config.xml"
+
+#include <android/hardware_buffer.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
+
+#include <set>
+#include <string>
+#include "tinyxml2.h"
+#include <vector>
+
+using tinyxml2::XMLElement;
+namespace android {
+
+enum ErrorCode : uint8_t {
+    // OK status.
+    STATUS_OK = 0,
+
+    // Error status. Cannot read the config file (config file missing or not
+    // accessible)
+    ERROR_READ_CONFIG_FILE = 1,
+
+    // Error status. Config file format doesn't match.
+    ERROR_CONFIG_FILE_FORMAT = 2,
+
+    // Error status. Config reader hasn't been initialized.
+    ERROR_CONFIG_READER_UNINITIALIZED = 3,
+
+    // Error status. Bad parameter.
+    ERROR_BAD_PARAMETER = 4,
+};
+
+inline const std::set<int64_t> VALID_COLOR_SPACES = {
+        ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED,
+        ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB,
+        ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3,
+        ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG,
+};
+
+inline const std::set<int64_t> VALID_SURFACE_TYPES = {
+        OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW,
+        OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE,
+        OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER,
+        OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC,
+        OutputConfiguration::SURFACE_TYPE_IMAGE_READER,
+};
+
+inline const std::set<int64_t> VALID_STREAM_USE_CASES = {
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW,
+        ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START,
+};
+
+inline const std::set<int64_t> VALID_TIMESTAMP_BASES = {
+        OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+        OutputConfiguration::TIMESTAMP_BASE_SENSOR,
+        OutputConfiguration::TIMESTAMP_BASE_MONOTONIC,
+        OutputConfiguration::TIMESTAMP_BASE_REALTIME,
+        OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED,
+        OutputConfiguration::TIMESTAMP_BASE_MAX,
+};
+
+inline const std::set<int64_t> VALID_MIRROR_MODES = {
+        OutputConfiguration::MIRROR_MODE_AUTO,
+        OutputConfiguration::MIRROR_MODE_NONE,
+        OutputConfiguration::MIRROR_MODE_H,
+        OutputConfiguration::MIRROR_MODE_V,
+};
+
+inline const std::set<int64_t> VALID_FORMATS = {
+        HAL_PIXEL_FORMAT_RGBA_8888,
+        HAL_PIXEL_FORMAT_RGBX_8888,
+        HAL_PIXEL_FORMAT_RGB_888,
+        HAL_PIXEL_FORMAT_RGB_565,
+        HAL_PIXEL_FORMAT_BGRA_8888,
+        HAL_PIXEL_FORMAT_YCBCR_422_SP,
+        HAL_PIXEL_FORMAT_YCRCB_420_SP,
+        HAL_PIXEL_FORMAT_YCBCR_422_I,
+        HAL_PIXEL_FORMAT_RGBA_FP16,
+        HAL_PIXEL_FORMAT_RAW16,
+        HAL_PIXEL_FORMAT_BLOB,
+        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+        HAL_PIXEL_FORMAT_YCBCR_420_888,
+        HAL_PIXEL_FORMAT_RAW_OPAQUE,
+        HAL_PIXEL_FORMAT_RAW10,
+        HAL_PIXEL_FORMAT_RAW12,
+        HAL_PIXEL_FORMAT_RGBA_1010102,
+        HAL_PIXEL_FORMAT_Y8,
+        HAL_PIXEL_FORMAT_Y16,
+        HAL_PIXEL_FORMAT_YV12,
+        HAL_PIXEL_FORMAT_DEPTH_16,
+        HAL_PIXEL_FORMAT_DEPTH_24,
+        HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8,
+        HAL_PIXEL_FORMAT_DEPTH_32F,
+        HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8,
+        HAL_PIXEL_FORMAT_STENCIL_8,
+        HAL_PIXEL_FORMAT_YCBCR_P010,
+        HAL_PIXEL_FORMAT_HSV_888,
+};
+
+inline const std::set<int64_t> VALID_USAGES = {
+        AHARDWAREBUFFER_USAGE_CPU_READ_NEVER,
+        AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
+        AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+        AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER,
+        AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
+        AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+        AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
+        AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT,
+        AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY,
+        AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT,
+        AHARDWAREBUFFER_USAGE_VIDEO_ENCODE,
+        AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA,
+        AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER,
+        AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP,
+        AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE,
+        AHARDWAREBUFFER_USAGE_FRONT_BUFFER,
+        AHARDWAREBUFFER_USAGE_VENDOR_0,
+        AHARDWAREBUFFER_USAGE_VENDOR_1,
+        AHARDWAREBUFFER_USAGE_VENDOR_2,
+        AHARDWAREBUFFER_USAGE_VENDOR_3,
+        AHARDWAREBUFFER_USAGE_VENDOR_4,
+        AHARDWAREBUFFER_USAGE_VENDOR_5,
+        AHARDWAREBUFFER_USAGE_VENDOR_6,
+        AHARDWAREBUFFER_USAGE_VENDOR_7,
+        AHARDWAREBUFFER_USAGE_VENDOR_8,
+        AHARDWAREBUFFER_USAGE_VENDOR_9,
+        AHARDWAREBUFFER_USAGE_VENDOR_10,
+        AHARDWAREBUFFER_USAGE_VENDOR_11,
+        AHARDWAREBUFFER_USAGE_VENDOR_12,
+        AHARDWAREBUFFER_USAGE_VENDOR_13,
+        AHARDWAREBUFFER_USAGE_VENDOR_14,
+        AHARDWAREBUFFER_USAGE_VENDOR_15,
+        AHARDWAREBUFFER_USAGE_VENDOR_16,
+        AHARDWAREBUFFER_USAGE_VENDOR_17,
+        AHARDWAREBUFFER_USAGE_VENDOR_18,
+};
+
+inline const std::set<int64_t> VALID_DATA_SPACES = {
+        HAL_DATASPACE_UNKNOWN,
+        HAL_DATASPACE_ARBITRARY,
+        HAL_DATASPACE_STANDARD_UNSPECIFIED,
+        HAL_DATASPACE_STANDARD_BT709,
+        HAL_DATASPACE_STANDARD_BT601_625,
+        HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED,
+        HAL_DATASPACE_STANDARD_BT601_525,
+        HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED,
+        HAL_DATASPACE_STANDARD_BT2020,
+        HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE,
+        HAL_DATASPACE_STANDARD_BT470M,
+        HAL_DATASPACE_STANDARD_FILM,
+        HAL_DATASPACE_STANDARD_DCI_P3,
+        HAL_DATASPACE_STANDARD_ADOBE_RGB,
+        HAL_DATASPACE_TRANSFER_UNSPECIFIED,
+        HAL_DATASPACE_TRANSFER_LINEAR,
+        HAL_DATASPACE_TRANSFER_SRGB,
+        HAL_DATASPACE_TRANSFER_SMPTE_170M,
+        HAL_DATASPACE_TRANSFER_GAMMA2_2,
+        HAL_DATASPACE_TRANSFER_GAMMA2_6,
+        HAL_DATASPACE_TRANSFER_GAMMA2_8,
+        HAL_DATASPACE_TRANSFER_ST2084,
+        HAL_DATASPACE_TRANSFER_HLG,
+        HAL_DATASPACE_RANGE_UNSPECIFIED,
+        HAL_DATASPACE_RANGE_FULL,
+        HAL_DATASPACE_RANGE_LIMITED,
+        HAL_DATASPACE_RANGE_EXTENDED,
+        HAL_DATASPACE_SRGB_LINEAR,
+        HAL_DATASPACE_V0_SRGB_LINEAR,
+        HAL_DATASPACE_V0_SCRGB_LINEAR,
+        HAL_DATASPACE_SRGB,
+        HAL_DATASPACE_V0_SRGB,
+        HAL_DATASPACE_V0_SCRGB,
+        HAL_DATASPACE_JFIF,
+        HAL_DATASPACE_V0_JFIF,
+        HAL_DATASPACE_BT601_625,
+        HAL_DATASPACE_V0_BT601_625,
+        HAL_DATASPACE_BT601_525,
+        HAL_DATASPACE_V0_BT601_525,
+        HAL_DATASPACE_BT709,
+        HAL_DATASPACE_V0_BT709,
+        HAL_DATASPACE_DCI_P3_LINEAR,
+        HAL_DATASPACE_DCI_P3,
+        HAL_DATASPACE_DISPLAY_P3_LINEAR,
+        HAL_DATASPACE_DISPLAY_P3,
+        HAL_DATASPACE_ADOBE_RGB,
+        HAL_DATASPACE_BT2020_LINEAR,
+        HAL_DATASPACE_BT2020,
+        HAL_DATASPACE_BT2020_PQ,
+        HAL_DATASPACE_DEPTH,
+        HAL_DATASPACE_SENSOR,
+};
+
+class SharedSessionConfigUtils {
+public:
+
+    // toString function for ErrorCode enum.
+    static const char* toString(ErrorCode errorCode);
+
+    // Convert string representation of colorspace to its int value.
+    static ErrorCode getColorSpaceFromStr(const char* colorSpaceStr, int32_t* colorSpace);
+
+    // Convert string representation of surface type to its int value.
+    static ErrorCode getSurfaceTypeFromXml(const XMLElement* surfaceTypeXml, int64_t* surfaceType);
+
+    // Convert string representation of width to its int value.
+    static ErrorCode getWidthFromXml(const XMLElement* widthXml, int64_t* width);
+
+    // Convert string representation of height to its int value.
+    static ErrorCode getHeightFromXml(const XMLElement* heightXml, int64_t* height);
+
+    // Convert string representation of physical cameraId to its std::string value.
+    static ErrorCode getPhysicalCameraIdFromXml(const XMLElement* physicalCameraIdXml,
+                                                std::string* physicalCameraId);
+
+    // Convert string representation of stream use case to its int64 value.
+    static ErrorCode getStreamUseCaseFromXml(const XMLElement* streamUseCaseXml,
+                                             int64_t* streamUseCase);
+
+    // Convert string representation of timestamp base to its int value.
+    static ErrorCode getTimestampBaseFromXml(const XMLElement* timestampBaseXml,
+                                             int64_t* timestampBase);
+
+    // Convert string representation of mirror mode to its int value.
+    static ErrorCode getMirrorModeFromXml(const XMLElement* mirrorModeXml, int64_t* mirrorMode);
+
+    // Convert string representation of use readout timestamp to its bool value.
+    static ErrorCode getUseReadoutTimestampFromXml(const XMLElement* useReadoutTimestampXml,
+                                                   bool* useReadoutTimestamp);
+
+    // Convert string representation of format to its int value.
+    static ErrorCode getFormatFromXml(const XMLElement* formatXml, int64_t* format,
+                                      int64_t surfaceType);
+
+    // Convert string representation of usage to its int64 value.
+    static ErrorCode getUsageFromXml(const XMLElement* usageXml, int64_t* usage,
+                                     int64_t surfaceType);
+
+    // Convert string representation of data space to its int value.
+    static ErrorCode getDataSpaceFromXml(const XMLElement* dataSpaceXml, int64_t* dataSpace);
+
+    static std::vector<std::string> splitString(std::string inputString, char delimiter);
+
+    static std::string setToString(const std::set<int64_t>& s);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_SERVERS_CAMERA_SHAREDSESSIONCONFIGUTILS_H_
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index bb54f25..e8de931 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2962,6 +2962,36 @@
     return retVal;
 }
 
+const sp<Camera3Device::CaptureRequest> Camera3Device::getOngoingRepeatingRequestLocked() {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mRequestThread != NULL) {
+        return mRequestThread->getOngoingRepeatingRequest();
+    }
+
+    return nullptr;
+}
+
+status_t Camera3Device::updateOngoingRepeatingRequestLocked(const SurfaceMap& surfaceMap) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mRequestThread != NULL) {
+        return mRequestThread->updateOngoingRepeatingRequest(surfaceMap);
+    }
+
+    return INVALID_OPERATION;
+}
+
+int64_t Camera3Device::getRepeatingRequestLastFrameNumberLocked() {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mRequestThread != NULL) {
+        return mRequestThread->getRepeatingRequestLastFrameNumber();
+    }
+
+    return hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
+}
+
 void Camera3Device::monitorMetadata(TagMonitor::eventSource source,
         int64_t frameNumber, nsecs_t timestamp, const CameraMetadata& metadata,
         const std::unordered_map<std::string, CameraMetadata>& physicalMetadata,
@@ -4228,6 +4258,60 @@
     return mLatestRequestInfo;
 }
 
+const sp<Camera3Device::CaptureRequest> Camera3Device::RequestThread::getOngoingRepeatingRequest() {
+    ATRACE_CALL();
+    Mutex::Autolock l(mRequestLock);
+
+    ALOGV("RequestThread::%s", __FUNCTION__);
+    if (mRepeatingRequests.empty()) {
+        return nullptr;
+    }
+
+    return *mRepeatingRequests.begin();
+}
+
+status_t Camera3Device::RequestThread::updateOngoingRepeatingRequest(const SurfaceMap& surfaceMap) {
+    ATRACE_CALL();
+    Mutex::Autolock l(mRequestLock);
+    if (mRepeatingRequests.empty()) {
+        return INVALID_OPERATION;
+    }
+
+    sp<CaptureRequest> curRequest = *mRepeatingRequests.begin();
+    std::vector<int32_t> outputStreamIds;
+    Vector<sp<camera3::Camera3OutputStreamInterface>> outputStreams;
+    for (const auto& [key, value] : surfaceMap) {
+        outputStreamIds.push_back(key);
+    }
+    for (auto id : outputStreamIds) {
+        sp<Camera3Device> parent = mParent.promote();
+        if (parent == nullptr) {
+            ALOGE("%s: parent does not exist!", __FUNCTION__);
+            return INVALID_OPERATION;
+        }
+        sp<Camera3OutputStreamInterface> stream = parent->mOutputStreams.get(id);
+        if (stream == nullptr) {
+            CLOGE("Request references unknown stream %d",id);
+            return BAD_VALUE;
+        }
+        outputStreams.push(stream);
+    }
+    curRequest->mOutputStreams = outputStreams;
+    curRequest->mOutputSurfaces = surfaceMap;
+
+    ALOGV("RequestThread::%s", __FUNCTION__);
+    return OK;
+
+}
+
+int64_t Camera3Device::RequestThread::getRepeatingRequestLastFrameNumber() {
+    ATRACE_CALL();
+    Mutex::Autolock l(mRequestLock);
+
+    ALOGV("RequestThread::%s", __FUNCTION__);
+    return mRepeatingLastFrameNumber;
+}
+
 bool Camera3Device::RequestThread::isStreamPending(
         sp<Camera3StreamInterface>& stream) {
     ATRACE_CALL();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3c45c1a..cdaaa4c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -38,6 +38,7 @@
 
 #include "common/CameraDeviceBase.h"
 #include "common/DepthPhotoProcessor.h"
+#include "common/FrameProcessorBase.h"
 #include "device3/BufferUtils.h"
 #include "device3/StatusTracker.h"
 #include "device3/Camera3BufferManager.h"
@@ -195,6 +196,40 @@
 
     status_t deleteStream(int id) override;
 
+    virtual status_t beginConfigure() override {return OK;};
+
+    virtual status_t getSharedStreamIds(const OutputStreamInfo& /*config*/,
+           std::vector< int>& /*streamIds*/) override {return INVALID_OPERATION;};
+
+    virtual status_t addSharedSurfaces(int /*streamId*/,
+            const std::vector<android::camera3::OutputStreamInfo>& /*outputInfo*/,
+            const std::vector<sp<Surface>>& /*surfaces*/,
+            std::vector<int>* /*surfaceIds*/) override {return INVALID_OPERATION;};
+
+    virtual status_t removeSharedSurfaces(int /*streamId*/,
+            const std::vector<size_t>& /*surfaceIds*/) override {return INVALID_OPERATION;};
+
+    virtual status_t setSharedStreamingRequest(
+            const PhysicalCameraSettingsList& /*request*/, const SurfaceMap& /*surfaceMap*/,
+            int32_t* /*sharedReqID*/, int64_t* /*lastFrameNumber = NULL*/) override {
+        return INVALID_OPERATION;
+    };
+
+    virtual status_t clearSharedStreamingRequest(int64_t* /*lastFrameNumber = NULL*/) override {
+        return INVALID_OPERATION;
+    };
+
+    virtual status_t setSharedCaptureRequest(const PhysicalCameraSettingsList& /*request*/,
+            const SurfaceMap& /*surfaceMap*/, int32_t* /*sharedReqID*/,
+            int64_t* /*lastFrameNumber = NULL*/) override {return INVALID_OPERATION;};
+
+    virtual sp<camera2::FrameProcessorBase> getSharedFrameProcessor() override {return nullptr;};
+
+    virtual status_t startStreaming(const int32_t /*reqId*/, const SurfaceMap& /*surfaceMap*/,
+            int32_t* /*sharedReqID*/, int64_t* /*lastFrameNumber = NULL*/)
+            override {return INVALID_OPERATION;};
+
+
     status_t configureStreams(const CameraMetadata& sessionParams,
             int operatingMode =
             camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) override;
@@ -213,7 +248,7 @@
     // Transitions to the idle state on success
     status_t waitUntilDrained() override;
 
-    status_t setNotifyCallback(wp<NotificationListener> listener) override;
+    virtual status_t setNotifyCallback(wp<NotificationListener> listener) override;
     bool     willNotify3A() override;
     status_t waitForNextFrame(nsecs_t timeout) override;
     status_t getNextResult(CaptureResult *frame) override;
@@ -750,6 +785,22 @@
     };
 
     /**
+     * Get the first repeating request in the ongoing repeating request list.
+     */
+    const sp<CaptureRequest> getOngoingRepeatingRequestLocked();
+
+    /**
+     * Update the first repeating request in the ongoing repeating request list
+     * with the surface map provided.
+     */
+    status_t updateOngoingRepeatingRequestLocked(const SurfaceMap& surfaceMap);
+
+    /**
+     * Get the repeating request last frame number.
+     */
+    int64_t getRepeatingRequestLastFrameNumberLocked();
+
+    /**
      * Get the last request submitted to the hal by the request thread.
      *
      * Must be called with mLock held.
@@ -1054,6 +1105,20 @@
          **/
         void wakeupLatestRequest(bool latestRequestFailed, int32_t latestRequestId);
 
+        /**
+         * Get the first repeating request in the ongoing repeating request list.
+         */
+        const sp<CaptureRequest> getOngoingRepeatingRequest();
+
+        /**
+         * Update the first repeating request in the ongoing repeating request list
+         * with the surface map provided.
+         */
+        status_t updateOngoingRepeatingRequest(const SurfaceMap& surfaceMap);
+
+        // Get the repeating request last frame number.
+        int64_t getRepeatingRequestLastFrameNumber();
+
       protected:
 
         virtual bool threadLoop();
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 0786622..f8d749a 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -134,6 +134,18 @@
             sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile),
             streamUseCase(_streamUseCase), timestampBase(_timestampBase), mirrorMode(_mirrorMode),
             colorSpace(_colorSpace) {}
+        bool operator == (const OutputStreamInfo& other) const {
+            return (width == other.width &&
+                    height == other.height &&
+                    format == other.format &&
+                    (other.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+                    (dataSpace == other.dataSpace && consumerUsage == other.consumerUsage)) &&
+                    sensorPixelModesUsed == other.sensorPixelModesUsed &&
+                    dynamicRangeProfile == other.dynamicRangeProfile &&
+                    colorSpace == other.colorSpace &&
+                    streamUseCase == other.streamUseCase &&
+                    timestampBase == other.timestampBase);
+    }
 };
 
 // Utility class to lock and unlock a GraphicBuffer
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index abc3f9c..474dfc7 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -72,7 +72,8 @@
     virtual status_t switchToOffline(const std::vector<int32_t>& /*streamsToKeep*/,
             /*out*/ sp<CameraOfflineSessionBase>* /*session*/) override;
 
-    status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags) override;
+    virtual status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags)
+            override;
 
     class AidlHalInterface : public Camera3Device::HalInterface {
      public:
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp
new file mode 100644
index 0000000..26dbe2d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp
@@ -0,0 +1,630 @@
+/*
+ * Copyright (C) 2024 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 "AidlCamera3-SharedDevice"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
+            ##__VA_ARGS__)
+
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
+            ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState(   \
+    "%s: " fmt, __FUNCTION__,              \
+    ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+    "%s: " fmt, __FUNCTION__,                    \
+    ##__VA_ARGS__)
+#define DECODE_VALUE(decoder, type, var) \
+  do { \
+    if (decoder.get##type(var) != OK) { \
+      return NOT_ENOUGH_DATA; \
+    } \
+  } while (0)
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <cstring>
+#include "../../common/aidl/AidlProviderInfo.h"
+#include "utils/SessionConfigurationUtils.h"
+#include "AidlCamera3SharedDevice.h"
+
+using namespace android::camera3;
+using namespace android::camera3::SessionConfigurationUtils;
+
+namespace android {
+
+class OpaqueConsumerListener : public BufferItemConsumer::FrameAvailableListener {
+public:
+    OpaqueConsumerListener(const wp<BufferItemConsumer>& consumer) : mConsumer(consumer) {}
+
+    virtual void onFrameAvailable(const BufferItem&) {
+        sp<BufferItemConsumer> consumer = mConsumer.promote();
+        if (consumer == nullptr) {
+            return;
+        }
+        BufferItem item;
+        consumer->acquireBuffer(&item, 0);
+        consumer->releaseBuffer(item, Fence::NO_FENCE);
+    }
+    virtual void onFrameReplaced(const BufferItem&) {}
+    virtual void onFrameDequeued(const uint64_t) {}
+    virtual void onFrameCancelled(const uint64_t) {}
+    virtual void onFrameDetached(const uint64_t) {}
+
+    wp<BufferItemConsumer> mConsumer;
+};
+
+// Metadata android.info.availableSharedOutputConfigurations has list of shared output
+// configurations. Each output configuration has minimum of 11 entries of size long
+// followed by the physical camera id if present.
+// See android.info.availableSharedOutputConfigurations for details.
+static const int SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES = 11;
+std::map<std::string, sp<AidlCamera3SharedDevice>> AidlCamera3SharedDevice::sSharedDevices;
+std::map<std::string, std::unordered_set<int>> AidlCamera3SharedDevice::sClientsPid;
+Mutex AidlCamera3SharedDevice::sSharedClientsLock;
+sp<AidlCamera3SharedDevice> AidlCamera3SharedDevice::getInstance(
+        std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+        std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+        const std::string& id, bool overrideForPerfClass, int rotationOverride,
+        bool legacyClient) {
+    Mutex::Autolock l(sSharedClientsLock);
+    if (sClientsPid[id].empty()) {
+        AidlCamera3SharedDevice* sharedDevice = new AidlCamera3SharedDevice(
+                cameraServiceProxyWrapper, attributionAndPermissionUtils, id, overrideForPerfClass,
+                rotationOverride, legacyClient);
+        sSharedDevices[id] = sharedDevice;
+    }
+    if (attributionAndPermissionUtils != nullptr) {
+        sClientsPid[id].insert(attributionAndPermissionUtils->getCallingPid());
+    }
+    return sSharedDevices[id];
+}
+
+status_t AidlCamera3SharedDevice::initialize(sp<CameraProviderManager> manager,
+        const std::string& monitorTags) {
+    ATRACE_CALL();
+    status_t res = OK;
+    Mutex::Autolock l(mSharedDeviceLock);
+    if (mStatus == STATUS_UNINITIALIZED) {
+        res = AidlCamera3Device::initialize(manager, monitorTags);
+        if (res == OK) {
+            mSharedOutputConfigurations = getSharedOutputConfiguration();
+            wp<NotificationListener> weakThis(this);
+            res = AidlCamera3Device::setNotifyCallback(weakThis);
+            if (res != OK) {
+                ALOGE("%s: Camera %s: Unable to set notify callback: %s (%d)",
+                        __FUNCTION__, mId.c_str(), strerror(-res), res);
+                return res;
+            }
+            mFrameProcessor = new camera2::FrameProcessorBase(this);
+            std::string threadName = std::string("CDU-") + mId + "-FrameProc";
+            res = mFrameProcessor->run(threadName.c_str());
+            if (res != OK) {
+                ALOGE("%s: Unable to start frame processor thread: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+                return res;
+            }
+        }
+    }
+    return res;
+}
+
+status_t AidlCamera3SharedDevice::disconnectClient(int clientPid) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    if (sClientsPid[mId].erase(clientPid) == 0) {
+        ALOGW("%s: Camera %s: Client %d is not connected to shared device", __FUNCTION__,
+                mId.c_str(), clientPid);
+    }
+
+    if (sClientsPid[mId].empty()) {
+        return Camera3Device::disconnect();
+    }
+    return OK;
+}
+
+std::vector<OutputConfiguration> AidlCamera3SharedDevice::getSharedOutputConfiguration() {
+    std::vector<OutputConfiguration> sharedConfigs;
+    int32_t colorspace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED;
+    camera_metadata_entry sharedSessionColorSpace = mDeviceInfo.find(
+            ANDROID_SHARED_SESSION_COLOR_SPACE);
+    if (sharedSessionColorSpace.count > 0) {
+        colorspace = *sharedSessionColorSpace.data.i32;
+    }
+    camera_metadata_entry sharedSessionConfigs = mDeviceInfo.find(
+            ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS);
+    if (sharedSessionConfigs.count > 0) {
+        int numOfEntries = sharedSessionConfigs.count;
+        int i = 0;
+        uint8_t physicalCameraIdLen;
+        int surfaceType, width, height, format, mirrorMode, timestampBase, dataspace;
+        long usage, streamUseCase;
+        bool isReadOutTimestampEnabled;
+        while (numOfEntries >= SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES) {
+            surfaceType = (int)sharedSessionConfigs.data.i64[i];
+            width = (int)sharedSessionConfigs.data.i64[i+1];
+            height = (int)sharedSessionConfigs.data.i64[i+2];
+            format = (int)sharedSessionConfigs.data.i64[i+3];
+            mirrorMode = (int)sharedSessionConfigs.data.i64[i+4];
+            isReadOutTimestampEnabled = (sharedSessionConfigs.data.i64[i+5] != 0);
+            timestampBase = (int)sharedSessionConfigs.data.i64[i+6];
+            dataspace = (int)sharedSessionConfigs.data.i64[i+7];
+            usage = sharedSessionConfigs.data.i64[i+8];
+            streamUseCase = sharedSessionConfigs.data.i64[i+9];
+            physicalCameraIdLen = sharedSessionConfigs.data.i64[i+10];
+            numOfEntries -= SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES;
+            i += SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES;
+            if (numOfEntries < physicalCameraIdLen) {
+                ALOGE("%s: Camera %s: Number of remaining data (%d entries) in shared configuration"
+                        " is less than physical camera id length %d. Malformed metadata"
+                        " android.info.availableSharedOutputConfigurations.", __FUNCTION__,
+                        mId.c_str(), numOfEntries, physicalCameraIdLen);
+                break;
+            }
+            std::string physicalCameraId;
+            long asciiValue;
+            for (int j = 0; j < physicalCameraIdLen; j++) {
+                asciiValue = sharedSessionConfigs.data.i64[i+j];
+                if (asciiValue == 0) { // Check for null terminator
+                    break;
+                }
+                physicalCameraId += static_cast<char>(asciiValue);
+            }
+            OutputConfiguration* outConfig = new OutputConfiguration(surfaceType, width, height,
+                    format, colorspace, mirrorMode, isReadOutTimestampEnabled, timestampBase,
+                    dataspace, usage, streamUseCase, physicalCameraId);
+            sharedConfigs.push_back(*outConfig);
+            i += physicalCameraIdLen;
+            numOfEntries -= physicalCameraIdLen;
+        }
+        if (numOfEntries != 0) {
+            ALOGE("%s: Camera %s: there are still %d entries left in shared output configuration."
+                    " Malformed metadata android.info.availableSharedOutputConfigurations.",
+                    __FUNCTION__, mId.c_str(), numOfEntries);
+        }
+    }
+    return sharedConfigs;
+}
+
+status_t AidlCamera3SharedDevice::beginConfigure() {
+    Mutex::Autolock l(mSharedDeviceLock);
+    status_t res;
+    int i = 0;
+
+    if (mStatus != STATUS_UNCONFIGURED) {
+        return OK;
+    }
+
+    mSharedSurfaces.clear();
+    mOpaqueConsumers.clear();
+    mSharedSurfaceIds.clear();
+    mStreamInfoMap.clear();
+
+    for (auto config : mSharedOutputConfigurations) {
+        std::vector<sp<Surface>> consumers;
+        android_dataspace dataspace = (android_dataspace)config.getDataspace();
+
+        if (config.getColorSpace()
+                != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED
+                && config.getFormat() != HAL_PIXEL_FORMAT_BLOB) {
+            if (!dataSpaceFromColorSpace(&dataspace, config.getColorSpace())) {
+                std::string msg = fmt::sprintf("Camera %s: color space %d not supported, "
+                    " failed to convert to data space", mId.c_str(), config.getColorSpace());
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                return INVALID_OPERATION;
+            }
+        }
+        std::unordered_set<int32_t> overriddenSensorPixelModes;
+        if (checkAndOverrideSensorPixelModesUsed(config.getSensorPixelModesUsed(),
+                config.getFormat(), config.getWidth(), config.getHeight(),
+                mDeviceInfo, &overriddenSensorPixelModes) != OK) {
+            std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
+                        "format %#x are not valid",mId.c_str(), config.getFormat());
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return INVALID_OPERATION;
+        }
+        #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+            sp<BufferItemConsumer> consumer = sp<BufferItemConsumer>::make(
+                    AHARDWAREBUFFER_USAGE_CAMERA_READ);
+            mOpaqueConsumers.push_back(consumer);
+            mSharedSurfaces.push_back(consumer->getSurface());
+        #else
+            sp<IGraphicBufferProducer> producer;
+            sp<IGraphicBufferConsumer> consumer;
+            BufferQueue::createBufferQueue(&producer, &consumer);
+            sp<BufferItemConsumer> opaqueConsumer = sp<BufferItemConsumer>::make(consumer,
+                    AHARDWAREBUFFER_USAGE_CAMERA_READ);
+            mOpaqueConsumers.push_back(opaqueConsumer);
+            mSharedSurfaces.push_back(new Surface(producer));
+        #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+        sp<OpaqueConsumerListener> consumerListener = sp<OpaqueConsumerListener>::make(
+                mOpaqueConsumers[i]);
+        mOpaqueConsumers[i]->setFrameAvailableListener(consumerListener);
+        consumers.push_back(mSharedSurfaces[i]);
+        sp<Camera3SharedOutputStream> newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
+                config.getWidth(),config.getHeight(), config.getFormat(), config.getUsage(),
+                dataspace, static_cast<camera_stream_rotation_t>(config.getRotation()),
+                mTimestampOffset, config.getPhysicalCameraId(), overriddenSensorPixelModes,
+                getTransportType(), config.getSurfaceSetID(), mUseHalBufManager,
+                config.getDynamicRangeProfile(), config.getStreamUseCase(),
+                mDeviceTimeBaseIsRealtime, config.getTimestampBase(),
+                config.getColorSpace(), config.useReadoutTimestamp());
+        int id = newStream->getSurfaceId(consumers[0]);
+        if (id < 0) {
+            SET_ERR_L("Invalid surface id");
+            return BAD_VALUE;
+        }
+        mSharedSurfaceIds.push_back(id);
+        newStream->setStatusTracker(mStatusTracker);
+        newStream->setBufferManager(mBufferManager);
+        newStream->setImageDumpMask(mImageDumpMask);
+        res = mOutputStreams.add(mNextStreamId, newStream);
+        if (res < 0) {
+            SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
+            return res;
+        }
+        mSessionStatsBuilder.addStream(mNextStreamId);
+        OutputStreamInfo streamInfo(config.getWidth(),config.getHeight(), config.getFormat(),
+                dataspace, config.getUsage(), overriddenSensorPixelModes,
+                config.getDynamicRangeProfile(), config.getStreamUseCase(),
+                config.getTimestampBase(), config.getMirrorMode(), config.getColorSpace());
+        mStreamInfoMap[mNextStreamId++] = streamInfo;
+        i++;
+    }
+    CameraMetadata sessionParams;
+    res = configureStreams(sessionParams, CAMERA_STREAM_CONFIGURATION_NORMAL_MODE);
+    if (res != OK) {
+        std::string msg = fmt::sprintf("Camera %s: Error configuring streams: %s (%d)",
+                mId.c_str(), strerror(-res), res);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return res;
+    }
+    return OK;
+}
+
+status_t AidlCamera3SharedDevice::getSharedStreamIds(const OutputStreamInfo &config,
+        std::vector<int>& streamIds) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    streamIds.clear();
+
+    for (const auto& streamInfo : mStreamInfoMap) {
+        OutputStreamInfo info = streamInfo.second;
+        if (info == config) {
+            streamIds.push_back(streamInfo.first);
+        }
+    }
+
+    if (streamIds.empty()) {
+        return NAME_NOT_FOUND;
+    } else  {
+        return OK;
+    }
+}
+
+status_t AidlCamera3SharedDevice::addSharedSurfaces(int streamId,
+        const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+        const std::vector<sp<Surface>> &surfaces,  std::vector<int> *surfaceIds) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    KeyedVector<sp<Surface>, size_t> outputMap;
+    std::vector<size_t> removedSurfaceIds;
+    status_t res;
+    sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
+    if (stream == nullptr) {
+        CLOGE("Stream %d is unknown", streamId);
+        return BAD_VALUE;
+    }
+
+    res = updateStream(streamId, surfaces, outputInfo, removedSurfaceIds, &outputMap);
+    if (res != OK) {
+        CLOGE("Stream %d failed to update stream (error %d %s) ",
+              streamId, res, strerror(-res));
+        return res;
+    }
+    for (size_t i = 0 ; i < outputMap.size(); i++){
+        if (surfaceIds != nullptr) {
+            surfaceIds->push_back(outputMap.valueAt(i));
+        }
+    }
+    return OK;
+}
+
+status_t AidlCamera3SharedDevice::removeSharedSurfaces(int streamId,
+        const std::vector<size_t> &removedSurfaceIds) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    KeyedVector<sp<Surface>, size_t> outputMap;
+    std::vector<sp<Surface>> surfaces;
+    std::vector<OutputStreamInfo> outputInfo;
+    status_t res;
+    sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
+    if (stream == nullptr) {
+        CLOGE("Stream %d is unknown", streamId);
+        return BAD_VALUE;
+    }
+
+    res = updateStream(streamId, surfaces, outputInfo, removedSurfaceIds, &outputMap);
+    if (res != OK) {
+        CLOGE("Stream %d failed to update stream (error %d %s) ",
+              streamId, res, strerror(-res));
+        return res;
+    }
+    return OK;
+}
+
+SurfaceMap AidlCamera3SharedDevice::mergeSurfaceMaps(const SurfaceMap& map1,
+        const SurfaceMap& map2) {
+    SurfaceMap mergedMap = map1;
+
+    for (const auto& [key, value] : map2) {
+        // If the key exists in map1, append the values
+        if (mergedMap.count(key) > 0) {
+            mergedMap[key].insert(mergedMap[key].end(), value.begin(), value.end());
+        } else {
+            // Otherwise, insert the key-value pair from map2
+            mergedMap[key] = value;
+        }
+    }
+    return mergedMap;
+}
+
+SurfaceMap AidlCamera3SharedDevice::removeClientSurfaceMap(const SurfaceMap& map1,
+        const SurfaceMap& map2) {
+    SurfaceMap resultMap = map1;
+
+    for (const auto& [key, value2] : map2) {
+        auto it1 = resultMap.find(key);
+        if (it1 != resultMap.end()) {
+            // Key exists in both maps, remove matching values
+            std::vector<size_t>& value1 = it1->second;
+            for (size_t val2 : value2) {
+                value1.erase(std::remove(value1.begin(), value1.end(), val2), value1.end());
+            }
+
+            // If the vector is empty after removing, remove the key
+            if (value1.empty()) {
+                resultMap.erase(it1);
+            }
+        }
+    }
+    return resultMap;
+}
+
+status_t AidlCamera3SharedDevice::setSharedStreamingRequest(
+        const CameraDeviceBase::PhysicalCameraSettingsList &clientSettings,
+        const SurfaceMap &surfaceMap, int32_t *sharedReqID,
+        int64_t *lastFrameNumber) {
+    if ((sharedReqID == nullptr) || (lastFrameNumber == nullptr)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock l(mSharedDeviceLock);
+    auto requestIdEntry = clientSettings.begin()->metadata.find(ANDROID_REQUEST_ID);
+    if (requestIdEntry.count == 0) {
+        CLOGE("RequestID does not exist in metadata");
+        return BAD_VALUE;
+    }
+    int clientRequestId = requestIdEntry.data.i32[0];
+    CameraDeviceBase::PhysicalCameraSettingsList newSettings = clientSettings;
+    SurfaceMap newSurfaceMap = surfaceMap;
+    List<const CameraDeviceBase::PhysicalCameraSettingsList> settingsList;
+    std::list<SurfaceMap> surfaceMaps;
+    int32_t requestID = mRequestIdCounter;
+    const sp<CaptureRequest> curRequest = getOngoingRepeatingRequestLocked();
+
+    if (curRequest != nullptr) {
+        // If there is ongoing streaming going by secondary clients, then
+        // merge their surface map in the new repeating request.
+        newSurfaceMap = mergeSurfaceMaps(surfaceMap, curRequest->mOutputSurfaces);
+    }
+
+    std::vector<int32_t> outputStreamIds;
+    for (const auto& [key, value] : newSurfaceMap) {
+        outputStreamIds.push_back(key);
+    }
+    surfaceMaps.push_back(newSurfaceMap);
+    newSettings.begin()->metadata.update(ANDROID_REQUEST_ID, &requestID, /*size*/1);
+    mRequestIdCounter++;
+    newSettings.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+            &outputStreamIds[0], outputStreamIds.size());
+    settingsList.push_back(newSettings);
+    status_t  err = setStreamingRequestList(settingsList, surfaceMaps, lastFrameNumber);
+    if (err != OK) {
+        CLOGE("Cannot start shared streaming request");
+        return err;
+    }
+    mStreamingRequestId = requestID;
+    int clientPid = mAttributionAndPermissionUtils->getCallingPid();
+    mClientRequestIds[clientPid] = clientRequestId;
+    mClientSurfaces[clientPid] = surfaceMap;
+    *sharedReqID = mStreamingRequestId;
+
+    return err;
+}
+
+status_t AidlCamera3SharedDevice::clearSharedStreamingRequest(int64_t *lastFrameNumber) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    int clientPid = mAttributionAndPermissionUtils->getCallingPid();
+    const sp<CaptureRequest> curRequest = getOngoingRepeatingRequestLocked();
+    if (curRequest == nullptr) {
+        CLOGE("No streaming ongoing");
+        return INVALID_OPERATION;
+    }
+
+    SurfaceMap newSurfaceMap;
+    newSurfaceMap = removeClientSurfaceMap(curRequest->mOutputSurfaces, mClientSurfaces[clientPid]);
+    mClientRequestIds.erase(clientPid);
+    mClientSurfaces.erase(clientPid);
+    if (newSurfaceMap.empty()) {
+        status_t err = clearStreamingRequest(lastFrameNumber);
+        if (err != OK) {
+            CLOGE("Error clearing streaming request");
+        }
+        return err;
+    }
+    *lastFrameNumber = getRepeatingRequestLastFrameNumberLocked();
+    return updateOngoingRepeatingRequestLocked(newSurfaceMap);
+}
+
+status_t AidlCamera3SharedDevice::setSharedCaptureRequest(const PhysicalCameraSettingsList &request,
+        const SurfaceMap &surfaceMap, int32_t *sharedReqID, int64_t *lastFrameNumber) {
+    Mutex::Autolock l(mSharedDeviceLock);
+    if (sharedReqID == nullptr) {
+        return BAD_VALUE;
+    }
+    CameraDeviceBase::PhysicalCameraSettingsList newRequest = request;
+    int newReqID = mRequestIdCounter;
+    List<const CameraDeviceBase::PhysicalCameraSettingsList> settingsList;
+    std::list<SurfaceMap> surfaceMaps;
+    surfaceMaps.push_back(surfaceMap);
+    newRequest.begin()->metadata.update(ANDROID_REQUEST_ID, &newReqID, /*size*/1);
+    settingsList.push_back(newRequest);
+    mRequestIdCounter++;
+    status_t err = captureList(settingsList, surfaceMaps, lastFrameNumber);
+    if (err != OK) {
+        CLOGE("Cannot start shared capture request");
+        return err;
+    }
+    *sharedReqID = newReqID;
+
+    return err;
+}
+
+status_t AidlCamera3SharedDevice::startStreaming(const int32_t reqId, const SurfaceMap& surfaceMap,
+        int32_t* sharedReqID, int64_t* lastFrameNumber) {
+    ATRACE_CALL();
+
+    if ((sharedReqID == nullptr) || (lastFrameNumber ==  nullptr)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock l(mSharedDeviceLock);
+    const sp<CaptureRequest> curRequest = getOngoingRepeatingRequestLocked();
+    if (curRequest != nullptr) {
+        // If there is already repeating request ongoing, attach the surfaces to
+        // the request.
+        SurfaceMap newSurfaceMap = mergeSurfaceMaps(surfaceMap, curRequest->mOutputSurfaces);
+        updateOngoingRepeatingRequestLocked(newSurfaceMap);
+        *lastFrameNumber = getRepeatingRequestLastFrameNumberLocked();
+    } else {
+        // If there is no ongoing repeating request, then send a default
+        // request with template preview.
+        std::vector<int32_t> outputStreamIds;
+        for (const auto& [key, value] : surfaceMap) {
+            outputStreamIds.push_back(key);
+        }
+
+        CameraMetadata previewTemplate;
+        status_t err = createDefaultRequest(CAMERA_TEMPLATE_PREVIEW, &previewTemplate);
+        if (err != OK) {
+            ALOGE("%s: Failed to create default PREVIEW request: %s (%d)",
+                    __FUNCTION__, strerror(-err), err);
+            return err;
+        }
+        int32_t requestID = mRequestIdCounter;
+        previewTemplate.update(ANDROID_REQUEST_ID, &requestID, /*size*/1);
+        mRequestIdCounter++;
+        previewTemplate.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
+                outputStreamIds.size());
+        CameraDeviceBase::PhysicalCameraSettingsList previewSettings;
+        previewSettings.push_back({mId, previewTemplate});
+
+        List<const CameraDeviceBase::PhysicalCameraSettingsList> settingsList;
+        std::list<SurfaceMap> surfaceMaps;
+        settingsList.push_back(previewSettings);
+        surfaceMaps.push_back(surfaceMap);
+        err = setStreamingRequestList(settingsList, surfaceMaps, lastFrameNumber);
+        if (err != OK) {
+            CLOGE("Cannot start shared streaming request");
+            return err;
+        }
+        mStreamingRequestId = requestID;
+    }
+
+    int clientPid = mAttributionAndPermissionUtils->getCallingPid();
+    mClientRequestIds[clientPid] = reqId;
+    mClientSurfaces[clientPid] = surfaceMap;
+    *sharedReqID = mStreamingRequestId;
+    return OK;
+}
+
+status_t AidlCamera3SharedDevice::setNotifyCallback(wp<NotificationListener> listener) {
+    ATRACE_CALL();
+    Mutex::Autolock l(mSharedDeviceLock);
+
+    if (listener == NULL) {
+        return BAD_VALUE;
+    }
+    mClientListeners[mAttributionAndPermissionUtils->getCallingPid()] = listener;
+    return OK;
+}
+
+void AidlCamera3SharedDevice::notifyError(
+        int32_t errorCode,
+        const CaptureResultExtras& resultExtras) {
+    for (auto clientListener : mClientListeners) {
+        sp<NotificationListener> listener = clientListener.second.promote();
+        if (listener != NULL) {
+            listener->notifyError(errorCode, resultExtras);
+        }
+    }
+}
+
+status_t AidlCamera3SharedDevice::notifyActive(float maxPreviewFps) {
+    Mutex::Autolock l(mSharedDeviceActiveLock);
+    for (auto activeClient : mClientRequestIds) {
+        sp<NotificationListener> listener =  mClientListeners[activeClient.first].promote();
+        if (listener != NULL) {
+            listener->notifyActive(maxPreviewFps);
+        }
+    }
+
+    return OK;
+}
+
+void  AidlCamera3SharedDevice::notifyIdle(int64_t requestCount, int64_t resultErrorCount,
+                                     bool deviceError,
+                                     std::pair<int32_t, int32_t> mostRequestedFpsRange,
+                                     const std::vector<hardware::CameraStreamStats>& stats) {
+    Mutex::Autolock l(mSharedDeviceActiveLock);
+    for (auto clientListener : mClientListeners) {
+        sp<NotificationListener> listener =  clientListener.second.promote();
+        if (listener != NULL) {
+            listener->notifyIdle(requestCount, resultErrorCount, deviceError, mostRequestedFpsRange,
+                    stats);
+        }
+    }
+}
+
+void  AidlCamera3SharedDevice::notifyShutter(const CaptureResultExtras& resultExtras,
+        nsecs_t timestamp) {
+    for (auto clientListener : mClientListeners) {
+        sp<NotificationListener> listener =  clientListener.second.promote();
+        if (listener != NULL) {
+            listener->notifyShutter(resultExtras, timestamp);
+        }
+    }
+}
+
+}
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h
new file mode 100644
index 0000000..3886f59
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 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_AIDLCAMERA3SHAREDDEVICE_H
+#define ANDROID_SERVERS_AIDLCAMERA3SHAREDDEVICE_H
+
+#include <camera/camera2/OutputConfiguration.h>
+#include "common/FrameProcessorBase.h"
+#include "../Camera3SharedOutputStream.h"
+#include "AidlCamera3Device.h"
+namespace android {
+
+/**
+ * Shared CameraDevice for AIDL HAL devices.
+ */
+using ::android::camera3::Camera3SharedOutputStream;
+class AidlCamera3SharedDevice :
+        public AidlCamera3Device,
+        public NotificationListener {
+  public:
+    static sp<AidlCamera3SharedDevice> getInstance(
+            std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+            std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+            const std::string& id, bool overrideForPerfClass, int rotationOverride,
+            bool legacyClient = false);
+    status_t initialize(sp<CameraProviderManager> manager,
+            const std::string& monitorTags) override;
+    status_t disconnectClient(int clientPid) override;
+    status_t beginConfigure() override;
+    status_t getSharedStreamIds(const OutputStreamInfo &config,
+            std::vector<int>& streamIds) override;
+    status_t addSharedSurfaces(int streamId,
+            const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+            const std::vector<sp<Surface>>& surfaces,
+            std::vector<int> *surfaceIds = nullptr) override;
+    status_t removeSharedSurfaces(int streamId,
+            const std::vector<size_t> &surfaceIds) override;
+    status_t setSharedStreamingRequest(const PhysicalCameraSettingsList &request,
+            const SurfaceMap &surfaceMap, int32_t *sharedReqID, int64_t *lastFrameNumber = NULL)
+            override;
+    status_t clearSharedStreamingRequest(int64_t *lastFrameNumber = NULL) override;
+    status_t setSharedCaptureRequest(const PhysicalCameraSettingsList &request,
+            const SurfaceMap &surfaceMap, int32_t *sharedReqID, int64_t *lastFrameNumber = NULL)
+            override;
+    sp<camera2::FrameProcessorBase> getSharedFrameProcessor() override {return mFrameProcessor;};
+    status_t startStreaming(const int32_t reqId, const SurfaceMap &surfaceMap,
+            int32_t *sharedReqID, int64_t *lastFrameNumber = NULL);
+
+    status_t setNotifyCallback(wp<NotificationListener> listener) override;
+    virtual void notifyError(int32_t errorCode,
+                             const CaptureResultExtras &resultExtras) override;
+    virtual status_t notifyActive(float maxPreviewFps) override;
+    virtual void notifyIdle(int64_t requestCount, int64_t resultError, bool deviceError,
+            std::pair<int32_t, int32_t> mostRequestedFpsRange,
+            const std::vector<hardware::CameraStreamStats>& streamStats) override;
+    virtual void notifyShutter(const CaptureResultExtras &resultExtras,
+            nsecs_t timestamp) override;
+    virtual void notifyRequestQueueEmpty() {};
+    // Prepare api not supported for shared session
+    virtual void notifyPrepared(int /*streamId*/) {};
+    // Required only for API1
+    virtual void notifyAutoFocus(uint8_t /*newState*/, int /*triggerId*/) {};
+    virtual void notifyAutoExposure(uint8_t /*newState*/, int /*triggerId*/) {};
+    virtual void notifyAutoWhitebalance(uint8_t /*newState*/,
+            int /*triggerId*/) {};
+    virtual void notifyRepeatingRequestError(long /*lastFrameNumber*/) {};
+  private:
+    static std::map<std::string, sp<AidlCamera3SharedDevice>> sSharedDevices;
+    static std::map<std::string, std::unordered_set<int>> sClientsPid;
+    static Mutex sSharedClientsLock;
+    AidlCamera3SharedDevice(
+            std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+            std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+            const std::string& id, bool overrideForPerfClass, int rotationOverride,
+            bool legacyClient)
+        : AidlCamera3Device(cameraServiceProxyWrapper, attributionAndPermissionUtils, id,
+                  overrideForPerfClass, rotationOverride, legacyClient),
+        mStreamingRequestId(REQUEST_ID_NONE),
+        mRequestIdCounter(0) {}
+    std::vector<OutputConfiguration> getSharedOutputConfiguration();
+    std::vector<OutputConfiguration> mSharedOutputConfigurations;
+    std::vector<int> mSharedSurfaceIds;
+    std::vector<sp<Surface>> mSharedSurfaces;
+    std::vector<sp<BufferItemConsumer>> mOpaqueConsumers;
+    std::unordered_map<int32_t, OutputStreamInfo> mStreamInfoMap;
+    // Streaming request ID
+    int32_t mStreamingRequestId;
+    static const int32_t REQUEST_ID_NONE = -1;
+    int32_t mRequestIdCounter;
+    std::unordered_map<int, int32_t> mClientRequestIds;
+    std::unordered_map<int, SurfaceMap> mClientSurfaces;
+    std::unordered_map<int, wp<NotificationListener>> mClientListeners;
+    SurfaceMap mergeSurfaceMaps(const SurfaceMap& map1, const SurfaceMap& map2);
+    SurfaceMap removeClientSurfaceMap(const SurfaceMap& map1, const SurfaceMap& map2);
+    Mutex mSharedDeviceLock;
+    sp<camera2::FrameProcessorBase> mFrameProcessor;
+}; // class AidlCamera3SharedDevice
+}; // namespace android
+#endif
diff --git a/services/camera/libcameraservice/device3/deprecated/DeprecatedCamera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/deprecated/DeprecatedCamera3StreamSplitter.cpp
index c1113e5..445db13 100644
--- a/services/camera/libcameraservice/device3/deprecated/DeprecatedCamera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/deprecated/DeprecatedCamera3StreamSplitter.cpp
@@ -511,7 +511,8 @@
     uint64_t bufferId;
     if (bufferItem.mGraphicBuffer != nullptr) {
         mInputSlots[bufferItem.mSlot] = bufferItem;
-    } else if (bufferItem.mAcquireCalled) {
+    } else if (bufferItem.mAcquireCalled
+            && (mInputSlots[bufferItem.mSlot].mGraphicBuffer != nullptr)) {
         bufferItem.mGraphicBuffer = mInputSlots[bufferItem.mSlot].mGraphicBuffer;
         mInputSlots[bufferItem.mSlot].mFrameNumber = bufferItem.mFrameNumber;
     } else {
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
index 152002b..98a0dbb 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
@@ -86,6 +86,10 @@
         mCaptureResultMetadataQueue = metadataQueue;
     }
 
+    virtual binder::Status onClientSharedAccessPriorityChanged(bool /*primaryClient*/) {
+        return binder::Status::ok();
+    }
+
  private:
     // Wrapper struct so that parameters to onResultReceived callback may be
     // sent through an AMessage.
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 78fca4e..b31ccc6 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -72,6 +72,10 @@
         // empty implementation
         return binder::Status::ok();
     }
+    virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageId*/, int32_t /*deviceId*/, bool /*primaryClient*/) {
+        return binder::Status::ok();
+    }
 };
 
 } // implementation
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 59e892f..9d140f2 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -135,7 +135,7 @@
     binder::Status serviceRet = mAidlICameraService->connectDevice(
             callbacks, cameraId, 0/*oomScoreOffset*/,
             /*targetSdkVersion*/__ANDROID_API_FUTURE__, ROTATION_OVERRIDE_NONE,
-            clientAttribution, /*devicePolicy*/0, /*out*/&deviceRemote);
+            clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, /*out*/&deviceRemote);
     HStatus status = HStatus::NO_ERROR;
     if (!serviceRet.isOk()) {
         ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 12ac33f..c0c9182 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -740,6 +740,13 @@
         // No op
         return binder::Status::ok();
     }
+
+    virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageName*/, int32_t /*deviceId*/,
+            bool /*isPrimaryClient*/) {
+        // No op
+        return binder::Status::ok();
+    }
 };
 
 class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
@@ -780,6 +787,11 @@
     virtual binder::Status onRequestQueueEmpty() {
         return binder::Status::ok();
     }
+
+    virtual binder::Status onClientSharedAccessPriorityChanged(bool /*isPrimaryClient*/) {
+        return binder::Status::ok();
+    }
+
 };
 
 class Camera2Fuzzer {
@@ -808,7 +820,7 @@
         mCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
-                clientAttribution, /*devicePolicy*/0, &device);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
         if (device == nullptr) {
             continue;
         }
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index bbc10dc..50e43e6 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -112,6 +112,7 @@
         "Camera3StreamSplitterTest.cpp",
         "CameraPermissionsTest.cpp",
         "CameraProviderManagerTest.cpp",
+        "SharedSessionConfigUtilsTest.cpp",
     ],
 
 }
diff --git a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
index 50aeaca..ff58c4a 100644
--- a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
@@ -77,6 +77,13 @@
         // No op
         return binder::Status::ok();
     }
+
+    virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageName*/, int32_t /*deviceId*/,
+            bool /*isPrimaryClient*/) {
+        // No op
+        return binder::Status::ok();
+    }
 };
 
 // Empty device callback.
@@ -118,6 +125,10 @@
     virtual binder::Status onRequestQueueEmpty() {
         return binder::Status::ok();
     }
+
+    virtual binder::Status onClientSharedAccessPriorityChanged(bool /*isPrimaryClient*/) {
+        return binder::Status::ok();
+    }
 };
 
 // Override isCameraDisabled from the CameraServiceProxy with a flag.
@@ -242,7 +253,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &device);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
         AutoDisconnectDevice autoDisconnect(device);
         ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
         ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
@@ -257,7 +268,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &device);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
         AutoDisconnectDevice autoDisconnect(device);
         ASSERT_TRUE(status.isOk());
     }
@@ -281,7 +292,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &deviceA);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
         AutoDisconnectDevice autoDisconnectA(deviceA);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
@@ -289,7 +300,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &deviceB);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
         AutoDisconnectDevice autoDisconnectB(deviceB);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
@@ -315,7 +326,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &deviceA);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
         AutoDisconnectDevice autoDisconnectA(deviceA);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
@@ -323,7 +334,7 @@
                 sCameraService->connectDevice(callbacks, s.cameraId,
                 1/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
-                clientAttribution, /*devicePolicy*/0, &deviceB);
+                clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
         AutoDisconnectDevice autoDisconnectB(deviceB);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
diff --git a/services/camera/libcameraservice/tests/SharedSessionConfigUtilsTest.cpp b/services/camera/libcameraservice/tests/SharedSessionConfigUtilsTest.cpp
new file mode 100644
index 0000000..b763e23
--- /dev/null
+++ b/services/camera/libcameraservice/tests/SharedSessionConfigUtilsTest.cpp
@@ -0,0 +1,672 @@
+/*
+* Copyright 2024 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 "SharedSessionConfigUtilsTest"
+
+#include <android/hardware_buffer.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <system/camera_metadata.h>
+#include <system/graphics.h>
+
+#include <gtest/gtest.h>
+#include "../config/SharedSessionConfigUtils.h"
+#include <tinyxml2.h>
+
+using namespace android;
+using namespace tinyxml2;
+
+// Helper function to create an XML element with text
+XMLElement* CreateXMLElement(XMLDocument& doc, const char* elementName, const char* text) {
+    XMLElement* elem = doc.NewElement(elementName);
+    if (text != nullptr) {
+        elem->SetText(text);
+    }
+    doc.InsertEndChild(elem);
+    return elem;
+}
+
+// Test for SharedSessionConfigUtils::toString
+TEST(SharedSessionConfigUtilsTest, ToStringTest) {
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(ErrorCode::STATUS_OK), "STATUS_OK");
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(ErrorCode::ERROR_READ_CONFIG_FILE),
+                 "ERROR_READ_CONFIG_FILE");
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(ErrorCode::ERROR_CONFIG_FILE_FORMAT),
+                 "ERROR_CONFIG_FILE_FORMAT");
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(
+                         ErrorCode::ERROR_CONFIG_READER_UNINITIALIZED),
+                 "ERROR_CONFIG_READER_UNINITIALIZED");
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(ErrorCode::ERROR_BAD_PARAMETER),
+                 "ERROR_BAD_PARAMETER");
+
+    // Test default case (unknown ErrorCode)
+    EXPECT_STREQ(SharedSessionConfigUtils::toString(static_cast<ErrorCode>(999)), "");
+}
+
+// Test for SharedSessionConfigUtils::getColorSpaceFromStr
+TEST(SharedSessionConfigUtilsTest, GetColorSpaceFromStrTest) {
+    int32_t colorSpace;
+    // Test with nullptr
+    EXPECT_EQ(SharedSessionConfigUtils::getColorSpaceFromStr(nullptr, &colorSpace),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(colorSpace, ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
+
+    // Test with empty string
+    EXPECT_EQ(SharedSessionConfigUtils::getColorSpaceFromStr("", &colorSpace),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(colorSpace, ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
+
+    // Test with valid strings
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED),
+             ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED},
+            {std::to_string(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB),
+             ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB},
+            {std::to_string(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3),
+             ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3},
+            {std::to_string(ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG),
+             ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020_HLG}
+    };
+
+    for (const auto& testCase : testCases) {
+        EXPECT_EQ(SharedSessionConfigUtils::getColorSpaceFromStr(testCase.input.c_str(),
+                                                                 &colorSpace),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(colorSpace, testCase.expected);
+    }
+
+    // Test with invalid string
+    EXPECT_EQ(SharedSessionConfigUtils::getColorSpaceFromStr("-99", &colorSpace),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getSurfaceTypeFromXml
+TEST(SharedSessionConfigUtilsTest, GetSurfaceTypeFromXmlTest) {
+    int64_t surfaceType;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getSurfaceTypeFromXml(nullptr, &surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with empty text
+    XMLDocument doc;
+    XMLElement* emptyElem = CreateXMLElement(doc, "surfaceType", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getSurfaceTypeFromXml(emptyElem, &surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with valid surface types
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW),
+             OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW},
+            {std::to_string(OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE),
+             OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE},
+            {std::to_string(OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER),
+             OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER},
+            {std::to_string(OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC),
+             OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC},
+            {std::to_string(OutputConfiguration::SURFACE_TYPE_IMAGE_READER),
+             OutputConfiguration::SURFACE_TYPE_IMAGE_READER}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "surfaceType", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getSurfaceTypeFromXml(elem, &surfaceType),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(surfaceType, testCase.expected);
+    }
+
+    // Test with invalid surface type
+    XMLElement* invalidElem = CreateXMLElement(doc, "surfaceType", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getSurfaceTypeFromXml(invalidElem, &surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getWidthFromXml
+TEST(SharedSessionConfigUtilsTest, GetWidthFromXmlTest) {
+    int64_t width;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getWidthFromXml(nullptr, &width),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "width", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getWidthFromXml(emptyElem, &width),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with valid width
+    XMLElement* validElem = CreateXMLElement(doc, "width", "1920");
+    EXPECT_EQ(SharedSessionConfigUtils::getWidthFromXml(validElem, &width),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(width, 1920);
+
+    // Test with invalid width (negative)
+    XMLElement* invalidWidthElem = CreateXMLElement(doc, "width", "-100");
+    EXPECT_EQ(SharedSessionConfigUtils::getWidthFromXml(invalidWidthElem, &width),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(width, -100); // The method logs an error but still returns STATUS_OK
+
+    // Test with non-numeric width
+    XMLElement* nonNumericElem = CreateXMLElement(doc, "width", "abc");
+    EXPECT_EQ(SharedSessionConfigUtils::getWidthFromXml(nonNumericElem, &width),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(width, 0); // std::atoi returns 0 for non-numeric strings
+}
+
+// Test for SharedSessionConfigUtils::getHeightFromXml
+TEST(SharedSessionConfigUtilsTest, GetHeightFromXmlTest) {
+    int64_t height;
+
+    XMLDocument doc;
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getHeightFromXml(nullptr, &height),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "height", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getHeightFromXml(emptyElem, &height),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with valid height
+    XMLElement* validElem = CreateXMLElement(doc, "height", "1080");
+    EXPECT_EQ(SharedSessionConfigUtils::getHeightFromXml(validElem, &height), ErrorCode::STATUS_OK);
+    EXPECT_EQ(height, 1080);
+
+    // Test with invalid height (zero)
+    XMLElement* invalidHeightElem = CreateXMLElement(doc, "height", "0");
+    EXPECT_EQ(SharedSessionConfigUtils::getHeightFromXml(invalidHeightElem, &height),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(height, 0); // The method logs an error but still returns STATUS_OK
+
+    // Test with non-numeric height
+    XMLElement* nonNumericElem = CreateXMLElement(doc, "height", "xyz");
+    EXPECT_EQ(SharedSessionConfigUtils::getHeightFromXml(nonNumericElem, &height),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(height, 0); // std::atoi returns 0 for non-numeric strings
+}
+
+// Test for SharedSessionConfigUtils::getPhysicalCameraIdFromXml
+TEST(SharedSessionConfigUtilsTest, GetPhysicalCameraIdFromXmlTest) {
+    std::string physicalCameraId;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getPhysicalCameraIdFromXml(nullptr, &physicalCameraId),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(physicalCameraId, "");
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "physicalCameraId", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getPhysicalCameraIdFromXml(emptyElem, &physicalCameraId),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(physicalCameraId, "");
+
+    // Test with valid physical camera ID
+    XMLElement* validElem = CreateXMLElement(doc, "physicalCameraId", "physical_camera_1");
+    EXPECT_EQ(SharedSessionConfigUtils::getPhysicalCameraIdFromXml(validElem, &physicalCameraId),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(physicalCameraId, "physical_camera_1");
+}
+
+// Test for SharedSessionConfigUtils::getStreamUseCaseFromXml
+TEST(SharedSessionConfigUtilsTest, GetStreamUseCaseFromXmlTest) {
+    int64_t streamUseCase;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getStreamUseCaseFromXml(nullptr, &streamUseCase),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(streamUseCase, ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "streamUseCase", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getStreamUseCaseFromXml(emptyElem, &streamUseCase),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(streamUseCase, ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+
+    // Test with valid stream use cases
+    struct {
+        std::string input;
+        int64_t expected;
+    } testCases[] = {
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW},
+            {std::to_string(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START),
+             ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "streamUseCase", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getStreamUseCaseFromXml(elem, &streamUseCase),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(streamUseCase, testCase.expected);
+    }
+
+    // Test with invalid stream use case
+    XMLElement* invalidElem = CreateXMLElement(doc, "streamUseCase", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getStreamUseCaseFromXml(invalidElem, &streamUseCase),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getTimestampBaseFromXml
+TEST(SharedSessionConfigUtilsTest, GetTimestampBaseFromXmlTest) {
+    int64_t timestampBase;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getTimestampBaseFromXml(nullptr, &timestampBase),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(timestampBase, OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "timestampBase", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getTimestampBaseFromXml(emptyElem, &timestampBase),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(timestampBase, OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+
+    // Test with valid timestamp bases
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_DEFAULT),
+             OutputConfiguration::TIMESTAMP_BASE_DEFAULT},
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_SENSOR),
+             OutputConfiguration::TIMESTAMP_BASE_SENSOR},
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_MONOTONIC),
+             OutputConfiguration::TIMESTAMP_BASE_MONOTONIC},
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_REALTIME),
+             OutputConfiguration::TIMESTAMP_BASE_REALTIME},
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED),
+             OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED},
+            {std::to_string(OutputConfiguration::TIMESTAMP_BASE_MAX),
+             OutputConfiguration::TIMESTAMP_BASE_MAX}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "timestampBase", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getTimestampBaseFromXml(elem, &timestampBase),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(timestampBase, testCase.expected);
+    }
+
+    // Test with invalid timestamp base
+    XMLElement* invalidElem = CreateXMLElement(doc, "timestampBase", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getTimestampBaseFromXml(invalidElem, &timestampBase),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getMirrorModeFromXml
+TEST(SharedSessionConfigUtilsTest, GetMirrorModeFromXmlTest) {
+    int64_t mirrorMode;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getMirrorModeFromXml(nullptr, &mirrorMode),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(mirrorMode, OutputConfiguration::MIRROR_MODE_AUTO);
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "mirrorMode", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getMirrorModeFromXml(emptyElem, &mirrorMode),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(mirrorMode, OutputConfiguration::MIRROR_MODE_AUTO);
+
+    // Test with valid mirror modes
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(OutputConfiguration::MIRROR_MODE_AUTO),
+             OutputConfiguration::MIRROR_MODE_AUTO},
+            {std::to_string(OutputConfiguration::MIRROR_MODE_NONE),
+             OutputConfiguration::MIRROR_MODE_NONE},
+            {std::to_string(OutputConfiguration::MIRROR_MODE_H),
+             OutputConfiguration::MIRROR_MODE_H},
+            {std::to_string(OutputConfiguration::MIRROR_MODE_V),
+             OutputConfiguration::MIRROR_MODE_V}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "mirrorMode", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getMirrorModeFromXml(elem, &mirrorMode),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(mirrorMode, testCase.expected);
+    }
+
+    // Test with invalid mirror mode
+    XMLElement* invalidElem = CreateXMLElement(doc, "mirrorMode", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getMirrorModeFromXml(invalidElem, &mirrorMode),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getUseReadoutTimestampFromXml
+TEST(SharedSessionConfigUtilsTest, GetUseReadoutTimestampFromXmlTest) {
+    bool useReadoutTimestamp;
+
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getUseReadoutTimestampFromXml(nullptr,
+                                                                      &useReadoutTimestamp),
+              ErrorCode::STATUS_OK);
+    EXPECT_FALSE(useReadoutTimestamp);
+
+    XMLDocument doc;
+    // Test with empty text (should default to false)
+    XMLElement* emptyElem = CreateXMLElement(doc, "useReadoutTimestamp", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getUseReadoutTimestampFromXml(emptyElem,
+                                                                      &useReadoutTimestamp),
+              ErrorCode::STATUS_OK);
+    EXPECT_FALSE(useReadoutTimestamp);
+
+    // Test with "true"
+    XMLElement* trueElem = CreateXMLElement(doc, "useReadoutTimestamp", "1");
+    EXPECT_EQ(SharedSessionConfigUtils::getUseReadoutTimestampFromXml(trueElem,
+                                                                      &useReadoutTimestamp),
+              ErrorCode::STATUS_OK);
+    EXPECT_TRUE(useReadoutTimestamp);
+
+    // Test with "false"
+    XMLElement* falseElem = CreateXMLElement(doc, "useReadoutTimestamp", "0");
+    EXPECT_EQ(SharedSessionConfigUtils::getUseReadoutTimestampFromXml(falseElem,
+                                                                      &useReadoutTimestamp),
+              ErrorCode::STATUS_OK);
+    EXPECT_FALSE(useReadoutTimestamp);
+
+    // Test with invalid string
+    XMLElement* invalidElem = CreateXMLElement(doc, "useReadoutTimestamp", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getUseReadoutTimestampFromXml(invalidElem,
+                                                                      &useReadoutTimestamp),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getFormatFromXml
+TEST(SharedSessionConfigUtilsTest, GetFormatFromXmlTest) {
+    int64_t format;
+
+    int64_t surfaceType = OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE;
+    // Test with nullptr XML element with surfaceType != IMAGE_READER
+    EXPECT_EQ(SharedSessionConfigUtils::getFormatFromXml(nullptr, &format, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(format, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+
+    surfaceType = OutputConfiguration::SURFACE_TYPE_IMAGE_READER;
+    // Test with nullptr XML element with surfaceType == IMAGE_READER
+    EXPECT_EQ(SharedSessionConfigUtils::getFormatFromXml(nullptr, &format, surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "format", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getFormatFromXml(emptyElem, &format, surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // Test with valid formats
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(HAL_PIXEL_FORMAT_RGBA_8888), HAL_PIXEL_FORMAT_RGBA_8888},
+            {std::to_string(HAL_PIXEL_FORMAT_RGBX_8888), HAL_PIXEL_FORMAT_RGBX_8888},
+            {std::to_string(HAL_PIXEL_FORMAT_RGB_888), HAL_PIXEL_FORMAT_RGB_888},
+            {std::to_string(HAL_PIXEL_FORMAT_RGB_565), HAL_PIXEL_FORMAT_RGB_565},
+            {std::to_string(HAL_PIXEL_FORMAT_BGRA_8888), HAL_PIXEL_FORMAT_BGRA_8888},
+            {std::to_string(HAL_PIXEL_FORMAT_YCBCR_422_SP), HAL_PIXEL_FORMAT_YCBCR_422_SP},
+            {std::to_string(HAL_PIXEL_FORMAT_YCRCB_420_SP), HAL_PIXEL_FORMAT_YCRCB_420_SP},
+            {std::to_string(HAL_PIXEL_FORMAT_YCBCR_422_I), HAL_PIXEL_FORMAT_YCBCR_422_I},
+            {std::to_string(HAL_PIXEL_FORMAT_RGBA_FP16), HAL_PIXEL_FORMAT_RGBA_FP16},
+            {std::to_string(HAL_PIXEL_FORMAT_RAW16), HAL_PIXEL_FORMAT_RAW16},
+            {std::to_string(HAL_PIXEL_FORMAT_BLOB), HAL_PIXEL_FORMAT_BLOB},
+            {std::to_string(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+             HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED},
+            {std::to_string(HAL_PIXEL_FORMAT_YCBCR_420_888), HAL_PIXEL_FORMAT_YCBCR_420_888},
+            {std::to_string(HAL_PIXEL_FORMAT_RAW_OPAQUE), HAL_PIXEL_FORMAT_RAW_OPAQUE},
+            {std::to_string(HAL_PIXEL_FORMAT_RAW10), HAL_PIXEL_FORMAT_RAW10},
+            {std::to_string(HAL_PIXEL_FORMAT_RAW12), HAL_PIXEL_FORMAT_RAW12},
+            {std::to_string(HAL_PIXEL_FORMAT_RGBA_1010102), HAL_PIXEL_FORMAT_RGBA_1010102},
+            {std::to_string(HAL_PIXEL_FORMAT_Y8), HAL_PIXEL_FORMAT_Y8},
+            {std::to_string(HAL_PIXEL_FORMAT_Y16), HAL_PIXEL_FORMAT_Y16},
+            {std::to_string(HAL_PIXEL_FORMAT_YV12), HAL_PIXEL_FORMAT_YV12},
+            {std::to_string(HAL_PIXEL_FORMAT_DEPTH_16), HAL_PIXEL_FORMAT_DEPTH_16},
+            {std::to_string(HAL_PIXEL_FORMAT_DEPTH_24), HAL_PIXEL_FORMAT_DEPTH_24},
+            {std::to_string(HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8),
+             HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8},
+            {std::to_string(HAL_PIXEL_FORMAT_DEPTH_32F), HAL_PIXEL_FORMAT_DEPTH_32F},
+            {std::to_string(HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8),
+             HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8},
+            {std::to_string(HAL_PIXEL_FORMAT_STENCIL_8), HAL_PIXEL_FORMAT_STENCIL_8},
+            {std::to_string(HAL_PIXEL_FORMAT_YCBCR_P010), HAL_PIXEL_FORMAT_YCBCR_P010},
+            {std::to_string(HAL_PIXEL_FORMAT_HSV_888), HAL_PIXEL_FORMAT_HSV_888}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "format", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getFormatFromXml(elem, &format, surfaceType),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(format, testCase.expected);
+    }
+
+    // Test with invalid format
+    XMLElement* invalidElem = CreateXMLElement(doc, "format", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getFormatFromXml(invalidElem, &format, surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getUsageFromXml
+TEST(SharedSessionConfigUtilsTest, GetUsageFromXmlTest) {
+    int64_t usage = 0;
+
+    int64_t surfaceType = OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE;
+    // Test with nullptr XML element with surfaceType == SURFACE_TYPE_SURFACE_TEXTURE
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(nullptr, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE));
+
+    // clear usage value
+    usage = 0;
+    surfaceType = OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW;
+    // Test with nullptr XML element with surfaceType == SURFACE_TYPE_SURFACE_VIEW
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(nullptr, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE
+                                          | AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY));
+
+    // clear usage value
+    usage = 0;
+    surfaceType = OutputConfiguration::SURFACE_TYPE_MEDIA_RECORDER;
+    // Test with nullptr XML element with surfaceType == SURFACE_TYPE_MEDIA_RECORDER
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(nullptr, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_VIDEO_ENCODE));
+
+    // clear usage value
+    usage = 0;
+    surfaceType = OutputConfiguration::SURFACE_TYPE_MEDIA_CODEC;
+    // Test with nullptr XML element with surfaceType == SURFACE_TYPE_MEDIA_CODEC
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(nullptr, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_VIDEO_ENCODE));
+
+    // clear usage value
+    usage = 0;
+    surfaceType = OutputConfiguration::SURFACE_TYPE_IMAGE_READER;
+    // Test with nullptr XML element with surfaceType == IMAGE_READER
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(nullptr, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER));
+
+
+    // clear usage value
+    usage = 0;
+    XMLDocument doc;
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "usage", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(emptyElem, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER));
+
+    // clear usage value
+    usage = 0;
+    // Test with valid single usage
+    XMLElement* singleUsageElem = CreateXMLElement(doc, "usage",
+                                                   std::to_string(
+                                                           AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN)
+                                                           .c_str());
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(singleUsageElem, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN));
+
+    // clear usage value
+    usage = 0;
+    // Test with valid multiple usages
+    XMLElement* multipleUsagesElem =
+            CreateXMLElement(doc, "usage",
+                             (std::to_string(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER)
+                                     + "|" + std::to_string(AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER)
+                                     + "|" + std::to_string(AHARDWAREBUFFER_USAGE_VIDEO_ENCODE))
+                                     .c_str());
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(multipleUsagesElem, &usage, surfaceType),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(usage, static_cast<int64_t>(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER
+                                          | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER
+                                          | AHARDWAREBUFFER_USAGE_VIDEO_ENCODE));
+
+    // clear usage value
+    usage = 0;
+    // Test with invalid usage
+    XMLElement* invalidUsageElem = CreateXMLElement(doc, "usage", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(invalidUsageElem, &usage, surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+
+    // clear usage value
+    usage = 0;
+    // Test with a mix of valid and invalid usages
+    XMLElement* mixedUsageElem =
+            CreateXMLElement(doc, "usage",
+                             (std::to_string(AHARDWAREBUFFER_USAGE_CPU_READ_NEVER) + "|-99")
+                                     .c_str());
+    EXPECT_EQ(SharedSessionConfigUtils::getUsageFromXml(mixedUsageElem, &usage, surfaceType),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
+
+// Test for SharedSessionConfigUtils::getDataSpaceFromXml
+TEST(SharedSessionConfigUtilsTest, GetDataSpaceFromXmlTest) {
+    int64_t dataSpace;
+
+    XMLDocument doc;
+    // Test with nullptr XML element
+    EXPECT_EQ(SharedSessionConfigUtils::getDataSpaceFromXml(nullptr, &dataSpace),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(dataSpace, HAL_DATASPACE_UNKNOWN);
+
+    // Test with empty text
+    XMLElement* emptyElem = CreateXMLElement(doc, "dataSpace", "");
+    EXPECT_EQ(SharedSessionConfigUtils::getDataSpaceFromXml(emptyElem, &dataSpace),
+              ErrorCode::STATUS_OK);
+    EXPECT_EQ(dataSpace, HAL_DATASPACE_UNKNOWN);
+
+    // Test with valid data spaces
+    struct {
+        std::string input;
+        int expected;
+    } testCases[] = {
+            {std::to_string(HAL_DATASPACE_UNKNOWN), HAL_DATASPACE_UNKNOWN},
+            {std::to_string(HAL_DATASPACE_ARBITRARY), HAL_DATASPACE_ARBITRARY},
+            {std::to_string(HAL_DATASPACE_STANDARD_UNSPECIFIED),
+             HAL_DATASPACE_STANDARD_UNSPECIFIED},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT709), HAL_DATASPACE_STANDARD_BT709},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT601_625), HAL_DATASPACE_STANDARD_BT601_625},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED),
+             HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT601_525), HAL_DATASPACE_STANDARD_BT601_525},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED),
+             HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT2020), HAL_DATASPACE_STANDARD_BT2020},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE),
+             HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE},
+            {std::to_string(HAL_DATASPACE_STANDARD_BT470M), HAL_DATASPACE_STANDARD_BT470M},
+            {std::to_string(HAL_DATASPACE_STANDARD_FILM), HAL_DATASPACE_STANDARD_FILM},
+            {std::to_string(HAL_DATASPACE_STANDARD_DCI_P3), HAL_DATASPACE_STANDARD_DCI_P3},
+            {std::to_string(HAL_DATASPACE_STANDARD_ADOBE_RGB), HAL_DATASPACE_STANDARD_ADOBE_RGB},
+            {std::to_string(HAL_DATASPACE_TRANSFER_UNSPECIFIED),
+             HAL_DATASPACE_TRANSFER_UNSPECIFIED},
+            {std::to_string(HAL_DATASPACE_TRANSFER_LINEAR), HAL_DATASPACE_TRANSFER_LINEAR},
+            {std::to_string(HAL_DATASPACE_TRANSFER_SRGB), HAL_DATASPACE_TRANSFER_SRGB},
+            {std::to_string(HAL_DATASPACE_TRANSFER_SMPTE_170M), HAL_DATASPACE_TRANSFER_SMPTE_170M},
+            {std::to_string(HAL_DATASPACE_TRANSFER_GAMMA2_2), HAL_DATASPACE_TRANSFER_GAMMA2_2},
+            {std::to_string(HAL_DATASPACE_TRANSFER_GAMMA2_6), HAL_DATASPACE_TRANSFER_GAMMA2_6},
+            {std::to_string(HAL_DATASPACE_TRANSFER_GAMMA2_8), HAL_DATASPACE_TRANSFER_GAMMA2_8},
+            {std::to_string(HAL_DATASPACE_TRANSFER_ST2084), HAL_DATASPACE_TRANSFER_ST2084},
+            {std::to_string(HAL_DATASPACE_TRANSFER_HLG), HAL_DATASPACE_TRANSFER_HLG},
+            {std::to_string(HAL_DATASPACE_RANGE_UNSPECIFIED), HAL_DATASPACE_RANGE_UNSPECIFIED},
+            {std::to_string(HAL_DATASPACE_RANGE_FULL), HAL_DATASPACE_RANGE_FULL},
+            {std::to_string(HAL_DATASPACE_RANGE_LIMITED), HAL_DATASPACE_RANGE_LIMITED},
+            {std::to_string(HAL_DATASPACE_RANGE_EXTENDED), HAL_DATASPACE_RANGE_EXTENDED},
+            {std::to_string(HAL_DATASPACE_SRGB_LINEAR), HAL_DATASPACE_SRGB_LINEAR},
+            {std::to_string(HAL_DATASPACE_V0_SRGB_LINEAR), HAL_DATASPACE_V0_SRGB_LINEAR},
+            {std::to_string(HAL_DATASPACE_V0_SCRGB_LINEAR), HAL_DATASPACE_V0_SCRGB_LINEAR},
+            {std::to_string(HAL_DATASPACE_SRGB), HAL_DATASPACE_SRGB},
+            {std::to_string(HAL_DATASPACE_V0_SRGB), HAL_DATASPACE_V0_SRGB},
+            {std::to_string(HAL_DATASPACE_V0_SCRGB), HAL_DATASPACE_V0_SCRGB},
+            {std::to_string(HAL_DATASPACE_JFIF), HAL_DATASPACE_JFIF},
+            {std::to_string(HAL_DATASPACE_V0_JFIF), HAL_DATASPACE_V0_JFIF},
+            {std::to_string(HAL_DATASPACE_BT601_625), HAL_DATASPACE_BT601_625},
+            {std::to_string(HAL_DATASPACE_V0_BT601_625), HAL_DATASPACE_V0_BT601_625},
+            {std::to_string(HAL_DATASPACE_BT601_525), HAL_DATASPACE_BT601_525},
+            {std::to_string(HAL_DATASPACE_V0_BT601_525), HAL_DATASPACE_V0_BT601_525},
+            {std::to_string(HAL_DATASPACE_BT709), HAL_DATASPACE_BT709},
+            {std::to_string(HAL_DATASPACE_V0_BT709), HAL_DATASPACE_V0_BT709},
+            {std::to_string(HAL_DATASPACE_DCI_P3_LINEAR), HAL_DATASPACE_DCI_P3_LINEAR},
+            {std::to_string(HAL_DATASPACE_DCI_P3), HAL_DATASPACE_DCI_P3},
+            {std::to_string(HAL_DATASPACE_DISPLAY_P3_LINEAR), HAL_DATASPACE_DISPLAY_P3_LINEAR},
+            {std::to_string(HAL_DATASPACE_DISPLAY_P3), HAL_DATASPACE_DISPLAY_P3},
+            {std::to_string(HAL_DATASPACE_ADOBE_RGB), HAL_DATASPACE_ADOBE_RGB},
+            {std::to_string(HAL_DATASPACE_BT2020_LINEAR), HAL_DATASPACE_BT2020_LINEAR},
+            {std::to_string(HAL_DATASPACE_BT2020), HAL_DATASPACE_BT2020},
+            {std::to_string(HAL_DATASPACE_BT2020_PQ), HAL_DATASPACE_BT2020_PQ},
+            {std::to_string(HAL_DATASPACE_DEPTH), HAL_DATASPACE_DEPTH},
+            {std::to_string(HAL_DATASPACE_SENSOR), HAL_DATASPACE_SENSOR}
+    };
+
+    for (const auto& testCase : testCases) {
+        XMLElement* elem = CreateXMLElement(doc, "dataSpace", testCase.input.c_str());
+        EXPECT_EQ(SharedSessionConfigUtils::getDataSpaceFromXml(elem, &dataSpace),
+                  ErrorCode::STATUS_OK);
+        EXPECT_EQ(dataSpace, testCase.expected);
+    }
+
+    // Test with invalid data space
+    XMLElement* invalidElem = CreateXMLElement(doc, "dataSpace", "-99");
+    EXPECT_EQ(SharedSessionConfigUtils::getDataSpaceFromXml(invalidElem, &dataSpace),
+              ErrorCode::ERROR_CONFIG_FILE_FORMAT);
+}
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 074c84d..8358b10 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -20,6 +20,7 @@
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
 #include <utils/Timers.h>
+#include <utils/Log.h>
 
 #include <algorithm>
 #include <utility>
@@ -27,6 +28,9 @@
 #include <set>
 #include <map>
 #include <memory>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
 
 namespace android {
 namespace resource_policy {
@@ -142,10 +146,10 @@
 public:
     ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
             const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-            bool isVendorClient, int32_t oomScoreOffset);
+            bool isVendorClient, int32_t oomScoreOffset, bool sharedMode = false);
     ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
             int32_t score, int32_t ownerId, int32_t state, bool isVendorClient,
-            int32_t oomScoreOffset);
+            int32_t oomScoreOffset, bool sharedMode = false);
 
     ~ClientDescriptor();
 
@@ -189,6 +193,11 @@
      */
     void setPriority(const ClientPriority& priority);
 
+    /**
+     * Returns true when camera is opened in shared mode.
+     */
+    bool getSharedMode() const;
+
     // This class is ordered by key
     template<class K, class V>
     friend bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b);
@@ -200,6 +209,7 @@
     std::set<KEY> mConflicting;
     ClientPriority mPriority;
     int32_t mOwnerId;
+    bool mSharedMode;
 }; // class ClientDescriptor
 
 template<class K, class V>
@@ -210,18 +220,19 @@
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
         const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-        bool isVendorClient, int32_t scoreOffset) :
+        bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
         mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
         mPriority(score, state, isVendorClient, scoreOffset),
-        mOwnerId{ownerId} {}
+        mOwnerId{ownerId}, mSharedMode{sharedMode} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
         std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
-        bool isVendorClient, int32_t scoreOffset) :
+        bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
         mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
         mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
-        mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId} {}
+        mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId},
+        mSharedMode{sharedMode} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -253,7 +264,10 @@
 
 template<class KEY, class VALUE>
 bool ClientDescriptor<KEY, VALUE>::isConflicting(const KEY& key) const {
-    if (key == mKey) return true;
+    // In shared mode, there can be more than one client using the camera.
+    // Hence, having more than one client with the same key is not considered as
+    // conflicting.
+    if (!mSharedMode && key == mKey) return true;
     for (const auto& x : mConflicting) {
         if (key == x) return true;
     }
@@ -266,6 +280,11 @@
 }
 
 template<class KEY, class VALUE>
+bool ClientDescriptor<KEY, VALUE>::getSharedMode() const {
+    return mSharedMode;
+}
+
+template<class KEY, class VALUE>
 void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
     // We don't use the usual copy constructor here since we want to remember
     // whether a client is a vendor client or not. This could have been wiped
@@ -349,14 +368,19 @@
     void removeAll();
 
     /**
-     * Remove and return the ClientDescriptor with a given key.
+     * Remove all ClientDescriptors with a given key.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> removeAll(const KEY& key);
+
+    /**
+     * Remove and return the ClientDescriptors with a given key.
      */
     std::shared_ptr<ClientDescriptor<KEY, VALUE>> remove(const KEY& key);
 
     /**
      * Remove the given ClientDescriptor.
      */
-    void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
+    virtual void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
 
     /**
      * Return a vector of the ClientDescriptors that would be evicted by adding the given
@@ -390,11 +414,19 @@
     std::vector<int32_t> getAllOwners() const;
 
     /**
+     * Return the ClientDescriptor for a client which has opened the camera in
+     * shared mode corresponding to the given pid.
+     */
+    std::shared_ptr<ClientDescriptor<KEY, VALUE>> getSharedClient(int pid) const;
+
+    /**
      * Return the ClientDescriptor corresponding to the given key, or an empty shared pointer
      * if none exists.
      */
     std::shared_ptr<ClientDescriptor<KEY, VALUE>> get(const KEY& key) const;
 
+    std::shared_ptr<ClientDescriptor<KEY, VALUE>> getPrimaryClient(const KEY& key) const;
+
     /**
      * Block until the given client is no longer in the active clients list, or the timeout
      * occurred.
@@ -495,6 +527,8 @@
     int32_t cost = client->getCost();
     ClientPriority priority = client->getPriority();
     int32_t owner = client->getOwnerId();
+    bool sharedMode = client->getSharedMode();
+
 
     int64_t totalCost = getCurrentCostLocked() + cost;
 
@@ -520,9 +554,10 @@
         int32_t curCost = i->getCost();
         ClientPriority curPriority = i->getPriority();
         int32_t curOwner = i->getOwnerId();
-
-        bool conflicting = (curKey == key || i->isConflicting(key) ||
-                client->isConflicting(curKey));
+        bool curSharedMode = i->getSharedMode();
+        bool conflicting;
+        conflicting = (((!sharedMode || !curSharedMode) && curKey == key)
+                || i->isConflicting(key) || client->isConflicting(curKey));
 
         if (!returnIncompatibleClients) {
             // Find evicted clients
@@ -647,6 +682,18 @@
 }
 
 template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getSharedClient(
+        int pid) const {
+    Mutex::Autolock lock(mLock);
+    for (const auto& i : mClients) {
+        if ((i->getOwnerId() == pid) && (i->getSharedMode())) {
+            return i;
+        }
+    }
+    return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
+}
+
+template<class KEY, class VALUE, class LISTENER>
 void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
         const std::map<int32_t,ClientPriority>& ownerPriorityList) {
     Mutex::Autolock lock(mLock);
@@ -669,6 +716,23 @@
 }
 
 template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getPrimaryClient(
+        const KEY& key) const {
+    Mutex::Autolock lock(mLock);
+    for (const auto& i : mClients) {
+        bool sharedMode =  i->getSharedMode();
+        bool primaryClient;
+        status_t ret = i->getValue()->isPrimaryClient(&primaryClient);
+        if (ret == OK) {
+            if ((i->getKey() == key) && sharedMode && primaryClient) {
+                return i;
+            }
+        }
+    }
+    return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
+}
+
+template<class KEY, class VALUE, class LISTENER>
 void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
     Mutex::Autolock lock(mLock);
     if (mListener != nullptr) {
@@ -681,6 +745,25 @@
 }
 
 template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+        ClientManager<KEY, VALUE, LISTENER>::removeAll(const KEY& key) {
+    Mutex::Autolock lock(mLock);
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> clients;
+    for (auto it = mClients.begin(); it != mClients.end();)
+    {
+        if ((*it)->getKey() == key) {
+            if (mListener != nullptr) mListener->onClientRemoved(**it);
+            clients.push_back(*it);
+            it = mClients.erase(it);
+        } else {
+            ++it;
+        }
+    }
+    mRemovedCondition.broadcast();
+    return clients;
+}
+
+template<class KEY, class VALUE, class LISTENER>
 std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
     const KEY& key) {
     Mutex::Autolock lock(mLock);