Merge "cameraserver: fix minor typo"
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 27ebb7a..8472562 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -37,6 +37,7 @@
         "libui",
         "libgui",
         "libbinder",
+        "libbinder_ndk",
         "libhidlbase",
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.provider@2.4",
@@ -59,6 +60,6 @@
     init_rc: ["cameraserver.rc"],
 
     vintf_fragments: [
-        "manifest_android.frameworks.cameraservice.service@2.2.xml",
+        "manifest_android.frameworks.cameraservice.service.xml",
     ],
 }
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
index 6a311f2..e307653 100644
--- a/camera/cameraserver/cameraserver.rc
+++ b/camera/cameraserver/cameraserver.rc
@@ -6,3 +6,4 @@
     task_profiles CameraServiceCapacity MaxPerformance
     rlimit rtprio 10 10
     onrestart class_restart cameraWatchdog
+    interface aidl android.frameworks.cameraservice.service.ICameraService/default
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
index cef8ef5..c494732 100644
--- a/camera/cameraserver/main_cameraserver.cpp
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include "CameraService.h"
+#include <android/binder_process.h>
 #include <hidl/HidlTransportSupport.h>
 
 using namespace android;
@@ -26,15 +27,21 @@
 {
     signal(SIGPIPE, SIG_IGN);
 
-    // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
-    // addition to consuming them from the Camera HAL as well.
+    // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls.
     hardware::configureRpcThreadpool(5, /*willjoin*/ false);
 
+    // Set 5 threads for VNDK AIDL calls. Now cameraserver will serve
+    // VNDK AIDL calls in addition to consuming them from the Camera HAL as well.
+    ABinderProcess_setThreadPoolMaxThreadCount(5);
+
     sp<ProcessState> proc(ProcessState::self());
     sp<IServiceManager> sm = defaultServiceManager();
     ALOGI("ServiceManager: %p", sm.get());
     CameraService::instantiate();
     ALOGI("ServiceManager: %p done instantiate", sm.get());
     ProcessState::self()->startThreadPool();
+    ABinderProcess_startThreadPool();
+
     IPCThreadState::self()->joinThreadPool();
+    ABinderProcess_joinThreadPool();
 }
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
new file mode 100644
index 0000000..e892471
--- /dev/null
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="framework">
+    <hal>
+        <name>android.frameworks.cameraservice.service</name>
+        <transport>hwbinder</transport>
+        <version>2.2</version>
+        <interface>
+            <name>ICameraService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+
+    <hal format="aidl">
+        <name>android.frameworks.cameraservice.service</name>
+        <version>1</version>
+        <interface>
+            <name>ICameraService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml
deleted file mode 100644
index eeafc91..0000000
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
-    <hal>
-        <name>android.frameworks.cameraservice.service</name>
-        <transport>hwbinder</transport>
-        <version>2.2</version>
-        <interface>
-            <name>ICameraService</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index fef873b..bfd02b3 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -141,6 +141,7 @@
     ],
 
     shared_libs: [
+        "libbinder_ndk",
         "libfmq",
         "libhidlbase",
         "libhardware",
@@ -151,15 +152,13 @@
         "libcutils",
         "libcamera_metadata",
         "libmediandk",
-        "android.frameworks.cameraservice.device@2.0",
-        "android.frameworks.cameraservice.device@2.1",
-        "android.frameworks.cameraservice.common@2.0",
-        "android.frameworks.cameraservice.service@2.0",
-        "android.frameworks.cameraservice.service@2.1",
-        "android.frameworks.cameraservice.service@2.2",
+        "android.frameworks.cameraservice.common-V1-ndk",
+        "android.frameworks.cameraservice.device-V1-ndk",
+        "android.frameworks.cameraservice.service-V1-ndk",
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
+        "libaidlcommonsupport",
         "libarect",
     ],
     // TODO: jchowdhary@, use header_libs instead b/131165718
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 9c98778..65b8837 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -29,6 +29,7 @@
 #include "impl/ACameraCaptureSession.h"
 
 #include "impl/ACameraCaptureSession.inc"
+
 #include "NdkCameraCaptureSession.inc"
 
 using namespace android;
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 691996b..8211671 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -22,18 +22,11 @@
 #include <utils/Trace.h>
 
 #include <camera/NdkCameraDevice.h>
+
 #include "impl/ACameraCaptureSession.h"
 
 using namespace android::acam;
 
-bool areWindowTypesEqual(ACameraWindowType *a, ACameraWindowType *b) {
-#ifdef __ANDROID_VNDK__
-    return utils::isWindowNativeHandleEqual(a, b);
-#else
-    return a == b;
-#endif
-}
-
 EXPORT
 camera_status_t ACameraDevice_close(ACameraDevice* device) {
     ATRACE_CALL();
@@ -183,14 +176,15 @@
                 __FUNCTION__);
         return ACAMERA_ERROR_INVALID_OPERATION;
     }
-    if (areWindowTypesEqual(out->mWindow, window)) {
+    if (out->isWindowEqual(window)) {
         ALOGE("%s: Error trying to add the same window associated with the output configuration",
                 __FUNCTION__);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
 
-    auto insert = out->mSharedWindows.insert(window);
-    camera_status_t ret = (insert.second) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
+
+    bool insert = out->addSharedWindow(window);
+    camera_status_t ret = (insert) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
     return ret;
 }
 
@@ -208,13 +202,13 @@
                 __FUNCTION__);
         return ACAMERA_ERROR_INVALID_OPERATION;
     }
-    if (areWindowTypesEqual(out->mWindow, window)) {
+    if (out->isWindowEqual(window)) {
         ALOGE("%s: Error trying to remove the same window associated with the output configuration",
                 __FUNCTION__);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
 
-    auto remove = out->mSharedWindows.erase(window);
+    auto remove = out->removeSharedWindow(window);
     camera_status_t ret = (remove) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
     return ret;
 }
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 3d231a8..2de4a50 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -81,7 +81,7 @@
                callback->onCameraAvailable, callback->onCameraUnavailable);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    CameraManagerGlobal::getInstance().registerAvailabilityCallback(callback);
+    CameraManagerGlobal::getInstance()->registerAvailabilityCallback(callback);
     return ACAMERA_OK;
 }
 
@@ -100,7 +100,7 @@
                callback->onCameraAvailable, callback->onCameraUnavailable);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    CameraManagerGlobal::getInstance().unregisterAvailabilityCallback(callback);
+    CameraManagerGlobal::getInstance()->unregisterAvailabilityCallback(callback);
     return ACAMERA_OK;
 }
 
@@ -131,7 +131,7 @@
             return ACAMERA_ERROR_INVALID_PARAMETER;
         }
     }
-    CameraManagerGlobal::getInstance().registerExtendedAvailabilityCallback(callback);
+    CameraManagerGlobal::getInstance()->registerExtendedAvailabilityCallback(callback);
     return ACAMERA_OK;
 }
 
@@ -154,7 +154,7 @@
                callback->onCameraAccessPrioritiesChanged);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    CameraManagerGlobal::getInstance().unregisterExtendedAvailabilityCallback(callback);
+    CameraManagerGlobal::getInstance()->unregisterExtendedAvailabilityCallback(callback);
     return ACAMERA_OK;
 }
 
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index 68db233..110d47a 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -23,7 +23,11 @@
 
 ACameraCaptureSession::~ACameraCaptureSession() {
     ALOGV("~ACameraCaptureSession: %p notify device end of life", this);
+#ifdef __ANDROID_VNDK__
+    std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
     sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
     if (dev != nullptr && !dev->isClosed()) {
         dev->lockDeviceForSessionOps();
         {
@@ -50,7 +54,11 @@
         mClosedByApp = true;
     }
 
+#ifdef __ANDROID_VNDK__
+    std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
     sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
     if (dev != nullptr) {
         dev->lockDeviceForSessionOps();
     }
@@ -75,7 +83,11 @@
 
 camera_status_t
 ACameraCaptureSession::stopRepeating() {
+#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;
@@ -93,7 +105,11 @@
 
 camera_status_t
 ACameraCaptureSession::abortCaptures() {
+#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;
@@ -110,7 +126,11 @@
 }
 
 camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
+#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;
@@ -129,7 +149,11 @@
 ACameraDevice*
 ACameraCaptureSession::getDevice() {
     Mutex::Autolock _l(mSessionLock);
+#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 nullptr;
@@ -143,6 +167,17 @@
     mIsClosed = true;
 }
 
+#ifdef __ANDROID_VNDK__
+std::shared_ptr<acam::CameraDevice>
+ACameraCaptureSession::getDevicePtr() {
+    std::shared_ptr<acam::CameraDevice> device = mDevice.lock();
+    if (device == nullptr || device->isClosed()) {
+        ALOGW("Device is closed but session %d is not notified", mId);
+        return nullptr;
+    }
+    return device;
+}
+#else
 sp<acam::CameraDevice>
 ACameraCaptureSession::getDeviceSp() {
     sp<acam::CameraDevice> device = mDevice.promote();
@@ -152,5 +187,4 @@
     }
     return device;
 }
-
-
+#endif
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 08a9226..cd65e8c 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -47,6 +47,21 @@
         return mWindow > other.mWindow;
     }
 
+    inline bool isWindowEqual(ACameraWindowType* window) const {
+        return mWindow == window;
+    }
+
+    // returns true if the window was successfully added, false otherwise.
+    inline bool addSharedWindow(ACameraWindowType* window) {
+        auto ret = mSharedWindows.insert(window);
+        return ret.second;
+    }
+
+    // returns the number of elements removed.
+    inline size_t removeSharedWindow(ACameraWindowType* window) {
+        return mSharedWindows.erase(window);
+    }
+
     ACameraWindowType* mWindow;
     std::set<ACameraWindowType *> mSharedWindows;
     bool           mIsShared;
@@ -65,6 +80,15 @@
  */
 struct ACameraCaptureSession : public RefBase {
   public:
+#ifdef __ANDROID_VNDK__
+    ACameraCaptureSession(
+            int id,
+            const ACaptureSessionOutputContainer* outputs,
+            const ACameraCaptureSession_stateCallbacks* cb,
+            std::weak_ptr<android::acam::CameraDevice> device) :
+            mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
+            mDevice(std::move(device)) {}
+#else
     ACameraCaptureSession(
             int id,
             const ACaptureSessionOutputContainer* outputs,
@@ -72,6 +96,7 @@
             android::acam::CameraDevice* device) :
             mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
             mDevice(device) {}
+#endif
 
     // This can be called in app calling close() or after some app callback is finished
     // Make sure the caller does not hold device or session lock!
@@ -114,12 +139,21 @@
     // or a new session is replacing this session.
     void closeByDevice();
 
+#ifdef __ANDROID_VNDK__
+    std::shared_ptr<android::acam::CameraDevice> getDevicePtr();
+#else
     sp<android::acam::CameraDevice> getDeviceSp();
+#endif
 
     const int mId;
     const ACaptureSessionOutputContainer mOutput;
     const ACameraCaptureSession_stateCallbacks mUserSessionCallback;
+#ifdef __ANDROID_VNDK__
+    const std::weak_ptr<android::acam::CameraDevice> mDevice;
+#else
     const wp<android::acam::CameraDevice> mDevice;
+#endif
+
     bool  mIsClosed = false;
     bool  mClosedByApp = false;
     Mutex mSessionLock;
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
index 86bf8a5..da535f8 100644
--- a/camera/ndk/impl/ACameraCaptureSession.inc
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -15,9 +15,8 @@
  */
 
 #include "ACameraCaptureSession.h"
-
 #ifdef __ANDROID_VNDK__
-#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#include <ndk_vendor/impl/ACameraDeviceVendor.inc>
 #else
 #include "ACameraDevice.inc"
 #endif
@@ -30,7 +29,11 @@
         /*optional*/T* cbs,
         int numRequests, ACaptureRequest** requests,
         /*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;
@@ -52,7 +55,11 @@
         /*optional*/T* cbs,
         int numRequests, ACaptureRequest** requests,
         /*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;
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 7997768..536055b 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1412,7 +1412,6 @@
     while (it != mSequenceLastFrameNumberMap.end()) {
         int sequenceId = it->first;
         int64_t lastFrameNumber = it->second.lastFrameNumber;
-        bool hasCallback = true;
 
         if (mRemote == nullptr) {
             ALOGW("Camera %s closed while checking sequence complete", getId());
@@ -1425,7 +1424,6 @@
             // This should not happen because we always register callback (with nullptr inside)
             if (mSequenceCallbackMap.count(sequenceId) == 0) {
                 ALOGW("No callback found for sequenceId %d", sequenceId);
-                hasCallback = false;
             }
 
             if (lastFrameNumber <= completedFrameNumber) {
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 23d90cc..9dc262f 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -38,17 +38,16 @@
 const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
 const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
 Mutex                CameraManagerGlobal::sLock;
-CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+wp<CameraManagerGlobal> CameraManagerGlobal::sInstance = nullptr;
 
-CameraManagerGlobal&
-CameraManagerGlobal::getInstance() {
+sp<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
     Mutex::Autolock _l(sLock);
-    CameraManagerGlobal* instance = sInstance;
+    sp<CameraManagerGlobal> instance = sInstance.promote();
     if (instance == nullptr) {
         instance = new CameraManagerGlobal();
         sInstance = instance;
     }
-    return *instance;
+    return instance;
 }
 
 CameraManagerGlobal::~CameraManagerGlobal() {
@@ -637,7 +636,7 @@
     Mutex::Autolock _l(mLock);
 
     std::vector<String8> idList;
-    CameraManagerGlobal::getInstance().getCameraIdList(&idList);
+    CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
 
     int numCameras = idList.size();
     ACameraIdList *out = new ACameraIdList;
@@ -687,7 +686,7 @@
         const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
     Mutex::Autolock _l(mLock);
 
-    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
     if (cs == nullptr) {
         ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
@@ -733,7 +732,7 @@
 
     ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
 
-    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
     if (cs == nullptr) {
         ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
         delete device;
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index d53d809..0dd79da 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -46,7 +46,7 @@
  */
 class CameraManagerGlobal final : public RefBase {
   public:
-    static CameraManagerGlobal& getInstance();
+    static sp<CameraManagerGlobal> getInstance();
     sp<hardware::ICameraService> getCameraService();
 
     void registerAvailabilityCallback(
@@ -257,7 +257,7 @@
 
     // For the singleton instance
     static Mutex sLock;
-    static CameraManagerGlobal* sInstance;
+    static wp<CameraManagerGlobal> sInstance;
     CameraManagerGlobal() {};
     ~CameraManagerGlobal();
 };
@@ -271,7 +271,7 @@
  */
 struct ACameraManager {
     ACameraManager() :
-            mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {}
+            mGlobalManager(android::acam::CameraManagerGlobal::getInstance()) {}
     ~ACameraManager();
     camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
     static void     deleteCameraIdList(ACameraIdList* cameraIdList);
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 152b786..6f97770 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3740,9 +3740,9 @@
      * <p>Output streams use this rectangle to produce their output, cropping to a smaller region
      * if necessary to maintain the stream's aspect ratio, then scaling the sensor input to
      * match the output's configured resolution.</p>
-     * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
-     * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage, they are not
-     * croppable. The crop region will be ignored by raw streams.</p>
+     * <p>The crop region is usually applied after the RAW to other color space (e.g. YUV)
+     * conversion. As a result RAW streams are not croppable unless supported by the
+     * camera device. See ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES#CROPPED_RAW for details.</p>
      * <p>For non-raw streams, any additional per-stream cropping will be done to maximize the
      * final pixel area of the stream.</p>
      * <p>For example, if the crop region is set to a 4:3 aspect ratio, then 4:3 streams will use
@@ -3833,6 +3833,7 @@
      * @see ACAMERA_CONTROL_ZOOM_RATIO
      * @see ACAMERA_DISTORTION_CORRECTION_MODE
      * @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
+     * @see ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES
      * @see ACAMERA_SCALER_CROPPING_TYPE
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
@@ -4488,6 +4489,59 @@
      */
     ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES =                 // int64[n] (acamera_metadata_enum_android_scaler_available_stream_use_cases_t)
             ACAMERA_SCALER_START + 25,
+    /**
+     * <p>The region of the sensor that corresponds to the RAW read out for this
+     * capture when the stream use case of a RAW stream is set to CROPPED_RAW.</p>
+     *
+     * <p>Type: int32[4]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     * </ul></p>
+     *
+     * <p>The coordinate system follows that of ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE.</p>
+     * <p>This CaptureResult key will be set when the corresponding CaptureRequest has a RAW target
+     * with stream use case set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW">CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW</a>,
+     * otherwise it will be {@code null}.
+     * The value of this key specifies the region of the sensor used for the RAW capture and can
+     * be used to calculate the corresponding field of view of RAW streams.
+     * This field of view will always be &gt;= field of view for (processed) non-RAW streams for the
+     * capture. Note: The region specified may not necessarily be centered.</p>
+     * <p>For example: Assume a camera device has a pre correction active array size of
+     * {@code {0, 0, 1500, 2000}}. If the RAW_CROP_REGION is {@code {500, 375, 1500, 1125}}, that
+     * corresponds to a centered crop of 1/4th of the full field of view RAW stream.</p>
+     * <p>The metadata keys which describe properties of RAW frames:</p>
+     * <ul>
+     * <li>ACAMERA_STATISTICS_HOT_PIXEL_MAP</li>
+     * <li>android.statistics.lensShadingCorrectionMap</li>
+     * <li>ACAMERA_LENS_DISTORTION</li>
+     * <li>ACAMERA_LENS_POSE_TRANSLATION</li>
+     * <li>ACAMERA_LENS_POSE_ROTATION</li>
+     * <li>ACAMERA_LENS_DISTORTION</li>
+     * <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
+     * </ul>
+     * <p>should be interpreted in the effective after raw crop field-of-view coordinate system.
+     * In this coordinate system,
+     * {preCorrectionActiveArraySize.left, preCorrectionActiveArraySize.top} corresponds to the
+     * the top left corner of the cropped RAW frame and
+     * {preCorrectionActiveArraySize.right, preCorrectionActiveArraySize.bottom} corresponds to
+     * the bottom right corner. Client applications must use the values of the keys
+     * in the CaptureResult metadata if present.</p>
+     * <p>Crop regions (android.scaler.CropRegion), AE/AWB/AF regions and face coordinates still
+     * use the ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE coordinate system as usual.</p>
+     *
+     * @see ACAMERA_LENS_DISTORTION
+     * @see ACAMERA_LENS_INTRINSIC_CALIBRATION
+     * @see ACAMERA_LENS_POSE_ROTATION
+     * @see ACAMERA_LENS_POSE_TRANSLATION
+     * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+     * @see ACAMERA_STATISTICS_HOT_PIXEL_MAP
+     */
+    ACAMERA_SCALER_RAW_CROP_REGION =                            // int32[4]
+            ACAMERA_SCALER_START + 26,
     ACAMERA_SCALER_END,
 
     /**
@@ -10207,6 +10261,30 @@
      */
     ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL             = 0x5,
 
+    /**
+     * <p>Cropped RAW stream when the client chooses to crop the field of view.</p>
+     * <p>Certain types of image sensors can run in binned modes in order to improve signal to
+     * noise ratio while capturing frames. However, at certain zoom levels and / or when
+     * other scene conditions are deemed fit, the camera sub-system may choose to un-bin and
+     * remosaic the sensor's output. This results in a RAW frame which is cropped in field
+     * of view and yet has the same number of pixels as full field of view RAW, thereby
+     * improving image detail.</p>
+     * <p>The resultant field of view of the RAW stream will be greater than or equal to
+     * croppable non-RAW streams. The effective crop region for this RAW stream will be
+     * reflected in the CaptureResult key ACAMERA_SCALER_RAW_CROP_REGION.</p>
+     * <p>If this stream use case is set on a non-RAW stream, i.e. not one of :</p>
+     * <ul>
+     * <li>{@link AIMAGE_FORMAT_RAW16 RAW_SENSOR}</li>
+     * <li>{@link AIMAGE_FORMAT_RAW10 RAW10}</li>
+     * <li>{@link AIMAGE_FORMAT_RAW12 RAW12}</li>
+     * </ul>
+     * <p>session configuration is not guaranteed to succeed.</p>
+     * <p>This stream use case may not be supported on some devices.</p>
+     *
+     * @see ACAMERA_SCALER_RAW_CROP_REGION
+     */
+    ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW            = 0x6,
+
 } acamera_metadata_enum_android_scaler_available_stream_use_cases_t;
 
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
index 5a1af79..45098c3 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
-#include <string>
 #include "utils.h"
 
+#include <android/binder_auto_utils.h>
+#include <string>
+#include <set>
+
+using ::android::acam::utils::native_handle_ptr_wrapper;
+
 struct ACaptureSessionOutput {
     explicit ACaptureSessionOutput(const native_handle_t* window, bool isShared = false,
             const char* physicalCameraId = "") :
@@ -38,8 +43,23 @@
         return mWindow > other.mWindow;
     }
 
-    android::acam::utils::native_handle_ptr_wrapper mWindow;
-    std::set<android::acam::utils::native_handle_ptr_wrapper> mSharedWindows;
+    inline bool isWindowEqual(ACameraWindowType* window) const {
+        return mWindow == native_handle_ptr_wrapper(window);
+    }
+
+    // returns true if the window was successfully added, false otherwise.
+    inline bool addSharedWindow(ACameraWindowType* window) {
+        auto ret = mSharedWindows.insert(window);
+        return ret.second;
+    }
+
+    // returns the number of elements removed.
+    inline size_t removeSharedWindow(ACameraWindowType* window) {
+        return mSharedWindows.erase(window);
+    }
+
+    native_handle_ptr_wrapper mWindow;
+    std::set<native_handle_ptr_wrapper> mSharedWindows;
     bool           mIsShared;
     int            mRotation = CAMERA3_STREAM_ROTATION_0;
     std::string mPhysicalCameraId;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 0a57590..96df7db 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -17,27 +17,34 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ACameraDeviceVendor"
 
-#include <vector>
-#include <inttypes.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <CameraMetadata.h>
-
-#include "ndk_vendor/impl/ACameraDevice.h"
 #include "ACameraCaptureSession.h"
 #include "ACameraMetadata.h"
 #include "ACaptureRequest.h"
+#include "ndk_vendor/impl/ACameraDevice.h"
 #include "utils.h"
+#include <CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <inttypes.h>
+#include <map>
+#include <utility>
+#include <vector>
 
-#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
-    if (!remoteRet.isOk()) { \
-        ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
-                  remoteRet.description().c_str()); \
-        return ACAMERA_ERROR_UNKNOWN; \
-    } \
-    if (status != Status::NO_ERROR) { \
-        ALOGE("%s: %s call failed", __FUNCTION__, callName); \
-        return utils::convertFromHidl(status); \
+#define CHECK_TRANSACTION_AND_RET(ret, callName)                                            \
+    if (!remoteRet.isOk()) {                                                                \
+        if (remoteRet.getExceptionCode() != EX_SERVICE_SPECIFIC) {                          \
+            ALOGE("%s: Transaction error during %s call %d", __FUNCTION__, callName,        \
+                                ret.getExceptionCode());                                    \
+            return ACAMERA_ERROR_UNKNOWN;                                                   \
+        } else {                                                                            \
+            Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());    \
+            std::string errorMsg =                                                          \
+                    aidl::android::frameworks::cameraservice::common::toString(errStatus);  \
+            ALOGE("%s: %s call failed: %s", __FUNCTION__, callName, errorMsg.c_str());      \
+            return utils::convertFromAidl(errStatus);                                       \
+        }                                                                                   \
     }
 
 using namespace android;
@@ -49,10 +56,10 @@
 namespace android {
 namespace acam {
 
-using HCameraMetadata = frameworks::cameraservice::device::V2_0::CameraMetadata;
-using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
-using SessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
-using hardware::Void;
+using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using ::ndk::ScopedAStatus;
 
 // Static member definitions
 const char* CameraDevice::kContextKey        = "Context";
@@ -81,7 +88,6 @@
         mCameraId(id),
         mAppCallbacks(*cb),
         mChars(std::move(chars)),
-        mServiceCallback(new ServiceCallback(this)),
         mWrapper(wrapper),
         mInError(false),
         mError(ACAMERA_OK),
@@ -125,8 +131,11 @@
 
 CameraDevice::~CameraDevice() { }
 
-void
-CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
+void CameraDevice::init() {
+    mServiceCallback = ndk::SharedRefBase::make<ServiceCallback>(weak_from_this());
+}
+
+void CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
     msg->post();
     msg.clear();
     sp<AMessage> cleanupMsg = new AMessage(kWhatCleanUpSessions, mHandler);
@@ -134,8 +143,7 @@
 }
 
 // TODO: cached created request?
-camera_status_t
-CameraDevice::createCaptureRequest(
+camera_status_t CameraDevice::createCaptureRequest(
         ACameraDevice_request_template templateId,
         const ACameraIdList* physicalCameraIdList,
         ACaptureRequest** request) const {
@@ -147,20 +155,16 @@
     if (mRemote == nullptr) {
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
-    CameraMetadata rawRequest;
-    Status status = Status::UNKNOWN_ERROR;
-    auto remoteRet = mRemote->createDefaultRequest(
-        utils::convertToHidl(templateId),
-        [&status, &rawRequest](auto s, const hidl_vec<uint8_t> &metadata) {
-            status = s;
-            if (status == Status::NO_ERROR && utils::convertFromHidlCloned(metadata, &rawRequest)) {
-            } else {
-                ALOGE("%s: Couldn't create default request", __FUNCTION__);
-            }
-        });
-    CHECK_TRANSACTION_AND_RET(remoteRet, status, "createDefaultRequest()")
+
+    AidlCameraMetadata aidlMetadata;
+    ScopedAStatus remoteRet = mRemote->createDefaultRequest(
+            utils::convertToAidl(templateId), &aidlMetadata);
+    CHECK_TRANSACTION_AND_RET(remoteRet, "createDefaultRequest()")
+
+    camera_metadata_t* rawRequest;
+    utils::cloneFromAidl(aidlMetadata, &rawRequest);
     ACaptureRequest* outReq = new ACaptureRequest();
-    outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+    outReq->settings = new ACameraMetadata(rawRequest, ACameraMetadata::ACM_REQUEST);
     if (physicalCameraIdList != nullptr) {
         for (auto i = 0; i < physicalCameraIdList->numCameras; i++) {
             outReq->physicalSettings.emplace(physicalCameraIdList->cameraIds[i],
@@ -172,9 +176,8 @@
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::createCaptureSession(
-        const ACaptureSessionOutputContainer*       outputs,
+camera_status_t CameraDevice::createCaptureSession(
+        const ACaptureSessionOutputContainer* outputs,
         const ACaptureRequest* sessionParameters,
         const ACameraCaptureSession_stateCallbacks* callbacks,
         /*out*/ACameraCaptureSession** session) {
@@ -199,7 +202,7 @@
     }
 
     ACameraCaptureSession* newSession = new ACameraCaptureSession(
-            mNextSessionId++, outputs, callbacks, this);
+            mNextSessionId++, outputs, callbacks, weak_from_this());
 
     // set new session as current session
     newSession->incStrong((void *) ACameraDevice_createCaptureSession);
@@ -225,41 +228,39 @@
     sessionConfig.outputStreams.resize(sessionOutputContainer->mOutputs.size());
     size_t index = 0;
     for (const auto& output : sessionOutputContainer->mOutputs) {
-        sessionConfig.outputStreams[index].rotation = utils::convertToHidl(output.mRotation);
-        sessionConfig.outputStreams[index].windowGroupId = -1;
-        sessionConfig.outputStreams[index].windowHandles.resize(output.mSharedWindows.size() + 1);
-        sessionConfig.outputStreams[index].windowHandles[0] = output.mWindow;
-        sessionConfig.outputStreams[index].physicalCameraId = output.mPhysicalCameraId;
+        OutputConfiguration& outputStream = sessionConfig.outputStreams[index];
+        outputStream.rotation = utils::convertToAidl(output.mRotation);
+        outputStream.windowGroupId = -1;
+        outputStream.windowHandles.resize(output.mSharedWindows.size() + 1);
+        outputStream.windowHandles[0] = std::move(dupToAidl(output.mWindow));
+        outputStream.physicalCameraId = output.mPhysicalCameraId;
         index++;
     }
 
     bool configSupported = false;
-    Status status = Status::UNKNOWN_ERROR;
-    auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
-        [&status, &configSupported](auto s, auto supported) {
-            status = s;
-            configSupported = supported;
-        });
-
-    CHECK_TRANSACTION_AND_RET(remoteRet, status, "isSessionConfigurationSupported()");
+    ScopedAStatus remoteRet = mRemote->isSessionConfigurationSupported(
+            sessionConfig, &configSupported);
+    CHECK_TRANSACTION_AND_RET(remoteRet, "isSessionConfigurationSupported()")
     return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
 }
 
 static void addMetadataToPhysicalCameraSettings(const CameraMetadata *metadata,
         const std::string &cameraId, PhysicalCameraSettings *physicalCameraSettings) {
-    CameraMetadata metadataCopy = *metadata;
-    camera_metadata_t *camera_metadata = metadataCopy.release();
-    HCameraMetadata hCameraMetadata;
-    utils::convertToHidl(camera_metadata, &hCameraMetadata, /*shouldOwn*/ true);
-    physicalCameraSettings->settings.metadata(std::move(hCameraMetadata));
+    const camera_metadata_t* cameraMetadata = metadata->getAndLock();
+    AidlCameraMetadata aidlCameraMetadata;
+    utils::convertToAidl(cameraMetadata, &aidlCameraMetadata);
+    metadata->unlock(cameraMetadata);
+    physicalCameraSettings->settings.set<CaptureMetadataInfo::metadata>(
+            std::move(aidlCameraMetadata));
     physicalCameraSettings->id = cameraId;
 }
 
 void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
         sp<CaptureRequest> &req) {
     req->mPhysicalCameraSettings.resize(1 + aCaptureRequest->physicalSettings.size());
-    addMetadataToPhysicalCameraSettings(&(aCaptureRequest->settings->getInternalData()), getId(),
-                    &(req->mPhysicalCameraSettings[0]));
+    addMetadataToPhysicalCameraSettings(
+            &(aCaptureRequest->settings->getInternalData()),
+            getId(),&(req->mPhysicalCameraSettings[0]));
     size_t i = 1;
     for (auto &physicalSetting : aCaptureRequest->physicalSettings) {
         addMetadataToPhysicalCameraSettings(&(physicalSetting.second->getInternalData()),
@@ -285,7 +286,7 @@
 
     int32_t streamId = -1;
     for (auto& kvPair : mConfiguredOutputs) {
-        if (utils::isWindowNativeHandleEqual(kvPair.second.first, output->mWindow)) {
+        if (kvPair.second.first == output->mWindow) {
             streamId = kvPair.first;
             break;
         }
@@ -295,56 +296,59 @@
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
 
-    OutputConfigurationWrapper outConfigW;
-    OutputConfiguration &outConfig = outConfigW.mOutputConfiguration;
-    outConfig.rotation = utils::convertToHidl(output->mRotation);
+    OutputConfiguration outConfig;
+    outConfig.rotation = utils::convertToAidl(output->mRotation);
     outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
-    outConfig.windowHandles[0] = output->mWindow;
+    outConfig.windowHandles[0] = std::move(dupToAidl(output->mWindow));
     outConfig.physicalCameraId = output->mPhysicalCameraId;
     int i = 1;
     for (auto& anw : output->mSharedWindows) {
-        outConfig.windowHandles[i++] = anw;
+        outConfig.windowHandles[i++] = std::move(dupToAidl(anw));
     }
 
-    auto remoteRet = mRemote->updateOutputConfiguration(streamId, outConfig);
+    auto remoteRet = mRemote->updateOutputConfiguration(streamId,
+                                                        outConfig);
+
     if (!remoteRet.isOk()) {
-        ALOGE("%s: Transaction error in updating OutputConfiguration: %s", __FUNCTION__,
-              remoteRet.description().c_str());
-        return ACAMERA_ERROR_UNKNOWN;
+        if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status st = static_cast<Status>(remoteRet.getServiceSpecificError());
+            switch (st) {
+                case Status::NO_ERROR:
+                    break;
+                case Status::INVALID_OPERATION:
+                    ALOGE("Camera device %s invalid operation", getId());
+                    return ACAMERA_ERROR_INVALID_OPERATION;
+                case Status::ALREADY_EXISTS:
+                    ALOGE("Camera device %s output surface already exists", getId());
+                    return ACAMERA_ERROR_INVALID_PARAMETER;
+                case Status::ILLEGAL_ARGUMENT:
+                    ALOGE("Camera device %s invalid input argument", getId());
+                    return ACAMERA_ERROR_INVALID_PARAMETER;
+                default:
+                    ALOGE("Camera device %s failed to add shared output", getId());
+                    return ACAMERA_ERROR_UNKNOWN;
+            }
+        } else {
+            ALOGE("%s: Transaction error in updating OutputConfiguration: %d", __FUNCTION__,
+                remoteRet.getExceptionCode());
+            return ACAMERA_ERROR_UNKNOWN;
+        }
     }
 
-    switch (remoteRet) {
-            case Status::NO_ERROR:
-                break;
-            case Status::INVALID_OPERATION:
-                ALOGE("Camera device %s invalid operation", getId());
-                return ACAMERA_ERROR_INVALID_OPERATION;
-            case Status::ALREADY_EXISTS:
-                ALOGE("Camera device %s output surface already exists", getId());
-                return ACAMERA_ERROR_INVALID_PARAMETER;
-            case Status::ILLEGAL_ARGUMENT:
-                ALOGE("Camera device %s invalid input argument", getId());
-                return ACAMERA_ERROR_INVALID_PARAMETER;
-            default:
-                ALOGE("Camera device %s failed to add shared output", getId());
-                return ACAMERA_ERROR_UNKNOWN;
-    }
-
-    mConfiguredOutputs[streamId] =
-            std::move(std::make_pair(std::move(output->mWindow), std::move(outConfigW)));
-
+    mConfiguredOutputs[streamId] = std::make_pair(output->mWindow,
+                                        std::move(outConfig));
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::allocateCaptureRequestLocked(
+camera_status_t CameraDevice::allocateCaptureRequestLocked(
         const ACaptureRequest* request, /*out*/sp<CaptureRequest> &outReq) {
     sp<CaptureRequest> req(new CaptureRequest());
     req->mCaptureRequest.physicalCameraSettings.resize(1 + request->physicalSettings.size());
 
     size_t index = 0;
     allocateOneCaptureRequestMetadata(
-            req->mCaptureRequest.physicalCameraSettings[index++], mCameraId, request->settings);
+            req->mCaptureRequest.physicalCameraSettings[index++],
+            mCameraId, request->settings);
 
     for (auto& physicalEntry : request->physicalSettings) {
         allocateOneCaptureRequestMetadata(
@@ -354,19 +358,20 @@
 
     std::vector<int32_t> requestStreamIdxList;
     std::vector<int32_t> requestSurfaceIdxList;
-    for (auto outputTarget : request->targets->mOutputs) {
-        const native_handle_t* anw = outputTarget.mWindow;
+
+    for (auto& outputTarget : request->targets->mOutputs) {
+        native_handle_ptr_wrapper anw = outputTarget.mWindow;
         bool found = false;
         req->mSurfaceList.push_back(anw);
         // lookup stream/surface ID
         for (const auto& kvPair : mConfiguredOutputs) {
             int streamId = kvPair.first;
-            const OutputConfigurationWrapper& outConfig = kvPair.second.second;
-            const auto& windowHandles = outConfig.mOutputConfiguration.windowHandles;
+            const OutputConfiguration& outConfig = kvPair.second.second;
+            const auto& windowHandles = outConfig.windowHandles;
             for (int surfaceId = 0; surfaceId < (int) windowHandles.size(); surfaceId++) {
-                // If two native handles are equivalent, so are their surfaces.
-                if (utils::isWindowNativeHandleEqual(windowHandles[surfaceId].getNativeHandle(),
-                                                      anw)) {
+                // If two window handles point to the same native window,
+                // they have the same surfaces.
+                if (utils::isWindowNativeHandleEqual(anw, windowHandles[surfaceId])) {
                     found = true;
                     requestStreamIdxList.push_back(streamId);
                     requestSurfaceIdxList.push_back(surfaceId);
@@ -378,7 +383,7 @@
             }
         }
         if (!found) {
-            ALOGE("Unconfigured output target %p in capture request!", anw);
+            ALOGE("Unconfigured output target %p in capture request!", anw.mWindow);
             return ACAMERA_ERROR_INVALID_PARAMETER;
         }
     }
@@ -395,54 +400,57 @@
         PhysicalCameraSettings& cameraSettings,
         const std::string& id, const sp<ACameraMetadata>& metadata) {
     cameraSettings.id = id;
-    // TODO: Do we really need to copy the metadata here ?
-    CameraMetadata metadataCopy = metadata->getInternalData();
-    camera_metadata_t *cameraMetadata = metadataCopy.release();
-    HCameraMetadata hCameraMetadata;
-    utils::convertToHidl(cameraMetadata, &hCameraMetadata, true);
-    if (metadata != nullptr) {
-        if (hCameraMetadata.data() != nullptr &&
-            mCaptureRequestMetadataQueue != nullptr &&
-            mCaptureRequestMetadataQueue->write(
-                reinterpret_cast<const uint8_t *>(hCameraMetadata.data()),
-                hCameraMetadata.size())) {
-            // The metadata field of the union would've been destructued, so no need
-            // to re-size it.
-            cameraSettings.settings.fmqMetadataSize(hCameraMetadata.size());
-        } else {
-            ALOGE("Fmq write capture result failed, falling back to hwbinder");
-            cameraSettings.settings.metadata(std::move(hCameraMetadata));
-        }
+
+    if (metadata == nullptr) {
+        return;
+    }
+
+    const camera_metadata_t* cameraMetadata = metadata->getInternalData().getAndLock();
+    AidlCameraMetadata aidlCameraMetadata;
+    utils::convertToAidl(cameraMetadata, &aidlCameraMetadata);
+    metadata->getInternalData().unlock(cameraMetadata);
+
+    if (aidlCameraMetadata.metadata.data() != nullptr &&
+        mCaptureRequestMetadataQueue != nullptr &&
+        mCaptureRequestMetadataQueue->write(
+                reinterpret_cast<const int8_t*>(aidlCameraMetadata.metadata.data()),
+                aidlCameraMetadata.metadata.size())) {
+        cameraSettings.settings.set<CaptureMetadataInfo::fmqMetadataSize>(
+                aidlCameraMetadata.metadata.size());
+    } else {
+        ALOGE("Fmq write capture result failed, falling back to hwbinder");
+        cameraSettings.settings.set<CaptureMetadataInfo::metadata>(std::move(aidlCameraMetadata));
     }
 }
 
 
-ACaptureRequest*
-CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req, const char* deviceId) {
+ACaptureRequest* CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req,
+                                                       const char* deviceId) {
     ACaptureRequest* pRequest = new ACaptureRequest();
     for (size_t i = 0; i < req->mPhysicalCameraSettings.size(); i++) {
         const std::string& id = req->mPhysicalCameraSettings[i].id;
-        CameraMetadata clone;
-        utils::convertFromHidlCloned(req->mPhysicalCameraSettings[i].settings.metadata(), &clone);
-        camera_metadata_t *clonep = clone.release();
+        camera_metadata_t* clone;
+        AidlCameraMetadata& aidlCameraMetadata = req->mPhysicalCameraSettings[i].settings
+                                                         .get<CaptureMetadataInfo::metadata>();
+        utils::cloneFromAidl(aidlCameraMetadata, &clone);
+
         if (id == deviceId) {
-            pRequest->settings = new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+            pRequest->settings = new ACameraMetadata(clone, ACameraMetadata::ACM_REQUEST);
         } else {
             pRequest->physicalSettings[req->mPhysicalCameraSettings[i].id] =
-                    new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+                    new ACameraMetadata(clone, ACameraMetadata::ACM_REQUEST);
         }
     }
     pRequest->targets = new ACameraOutputTargets();
     for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
-        const native_handle_t* anw = req->mSurfaceList[i];
+        native_handle_ptr_wrapper anw = req->mSurfaceList[i];
         ACameraOutputTarget outputTarget(anw);
-        pRequest->targets->mOutputs.insert(outputTarget);
+        pRequest->targets->mOutputs.insert(std::move(outputTarget));
     }
     return pRequest;
 }
 
-void
-CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
+void CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
     if (req == nullptr) {
         return;
     }
@@ -459,7 +467,7 @@
     }
 
     if (mCurrentSession != session) {
-        // Session has been replaced by other seesion or device is closed
+        // Session has been replaced by other session or device is closed
         return;
     }
     mCurrentSession = nullptr;
@@ -471,8 +479,8 @@
         return;
     }
 
-    // No new session, unconfigure now
-    // Note: The unconfiguration of session won't be accounted for session
+    // No new session, un-configure now
+    // Note: The un-configuration of session won't be accounted for session
     // latency because a stream configuration with 0 streams won't ever become
     // active.
     nsecs_t startTimeNs = systemTime();
@@ -494,8 +502,8 @@
         ALOGD("%s: binder disconnect reached", __FUNCTION__);
         auto ret = mRemote->disconnect();
         if (!ret.isOk()) {
-            ALOGE("%s: Transaction error while disconnecting device %s", __FUNCTION__,
-                  ret.description().c_str());
+            ALOGE("%s: Transaction error while disconnecting device %d", __FUNCTION__,
+                  ret.getExceptionCode());
         }
     }
     mRemote = nullptr;
@@ -505,8 +513,7 @@
     }
 }
 
-camera_status_t
-CameraDevice::stopRepeatingLocked() {
+camera_status_t CameraDevice::stopRepeatingLocked() {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
         ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
@@ -517,20 +524,14 @@
         mRepeatingSequenceId = REQUEST_ID_NONE;
 
         int64_t lastFrameNumber;
-        Status status = Status::UNKNOWN_ERROR;
-        auto remoteRet = mRemote->cancelRepeatingRequest(
-                [&status, &lastFrameNumber](Status s, auto frameNumber) {
-                    status = s;
-                    lastFrameNumber = frameNumber;
-                });
-        CHECK_TRANSACTION_AND_RET(remoteRet, status, "cancelRepeatingRequest()");
+        ScopedAStatus remoteRet = mRemote->cancelRepeatingRequest(&lastFrameNumber);
+        CHECK_TRANSACTION_AND_RET(remoteRet, "cancelRepeatingRequest()");
         checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
     }
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::flushLocked(ACameraCaptureSession* session) {
+camera_status_t CameraDevice::flushLocked(ACameraCaptureSession* session) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
         ALOGE("Camera %s abort captures failed! ret %d", getId(), ret);
@@ -571,20 +572,15 @@
     }
 
     int64_t lastFrameNumber;
-    Status status = Status::UNKNOWN_ERROR;
-    auto remoteRet = mRemote->flush([&status, &lastFrameNumber](auto s, auto frameNumber) {
-                                        status = s;
-                                        lastFrameNumber = frameNumber;
-                                    });
-    CHECK_TRANSACTION_AND_RET(remoteRet, status, "flush()")
+    ScopedAStatus remoteRet = mRemote->flush(&lastFrameNumber);
+    CHECK_TRANSACTION_AND_RET(remoteRet, "flush()")
     if (mRepeatingSequenceId != REQUEST_ID_NONE) {
         checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
     }
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::waitUntilIdleLocked() {
+camera_status_t CameraDevice::waitUntilIdleLocked() {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
         ALOGE("Wait until camera %s idle failed! ret %d", getId(), ret);
@@ -597,13 +593,13 @@
     }
 
     auto remoteRet = mRemote->waitUntilIdle();
-    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "waitUntilIdle()")
+    CHECK_TRANSACTION_AND_RET(remoteRet, "waitUntilIdle()")
     return ACAMERA_OK;
 }
 
-camera_status_t
-CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs,
-        const ACaptureRequest* sessionParameters, nsecs_t startTimeNs) {
+camera_status_t CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs,
+                                                     const ACaptureRequest* sessionParameters,
+                                                     nsecs_t startTimeNs) {
     ACaptureSessionOutputContainer emptyOutput;
     if (outputs == nullptr) {
         outputs = &emptyOutput;
@@ -614,31 +610,37 @@
         return ret;
     }
 
-    std::set<std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> outputSet;
-    for (auto outConfig : outputs->mOutputs) {
-        const native_handle_t* anw = outConfig.mWindow;
-        OutputConfigurationWrapper outConfigInsertW;
-        OutputConfiguration &outConfigInsert = outConfigInsertW.mOutputConfiguration;
-        outConfigInsert.rotation = utils::convertToHidl(outConfig.mRotation);
+    std::map<native_handle_ptr_wrapper, OutputConfiguration> handleToConfig;
+    for (const auto& outConfig : outputs->mOutputs) {
+        native_handle_ptr_wrapper anw = outConfig.mWindow;
+        OutputConfiguration outConfigInsert;
+        outConfigInsert.rotation = utils::convertToAidl(outConfig.mRotation);
         outConfigInsert.windowGroupId = -1;
         outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
-        outConfigInsert.windowHandles[0] = anw;
+        outConfigInsert.windowHandles[0] = std::move(dupToAidl(anw));
         outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
-        native_handle_ptr_wrapper wrap(anw);
-
-        outputSet.emplace(std::make_pair(std::move(anw), std::move(outConfigInsertW)));
+        handleToConfig.insert({anw, std::move(outConfigInsert)});
     }
-    std::set<std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> addSet = outputSet;
+
+    std::set<native_handle_ptr_wrapper> addSet;
+    for (auto& kvPair : handleToConfig) {
+        addSet.insert(kvPair.first);
+    }
+
     std::vector<int32_t> deleteList;
 
     // Determine which streams need to be created, which to be deleted
     for (auto& kvPair : mConfiguredOutputs) {
         int32_t streamId = kvPair.first;
         auto& outputPair = kvPair.second;
-        if (outputSet.count(outputPair)) {
-            deleteList.push_back(streamId); // Need to delete a no longer needed stream
+        auto& anw = outputPair.first;
+        auto& configuredOutput = outputPair.second;
+
+        auto itr = handleToConfig.find(anw);
+        if (itr != handleToConfig.end() && (itr->second) == configuredOutput) {
+            deleteList.push_back(streamId);
         } else {
-            addSet.erase(outputPair);        // No need to add already existing stream
+            addSet.erase(anw);
         }
     }
 
@@ -673,106 +675,96 @@
     mIdle = true;
 
     auto remoteRet = mRemote->beginConfigure();
-    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "beginConfigure()")
+    CHECK_TRANSACTION_AND_RET(remoteRet, "beginConfigure()")
 
     // delete to-be-deleted streams
     for (auto streamId : deleteList) {
         remoteRet = mRemote->deleteStream(streamId);
-        CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "deleteStream()")
+        CHECK_TRANSACTION_AND_RET(remoteRet, "deleteStream()")
         mConfiguredOutputs.erase(streamId);
     }
 
     // add new streams
-    for (const auto &outputPair : addSet) {
-        int streamId;
-        Status status = Status::UNKNOWN_ERROR;
-        auto ret = mRemote->createStream(outputPair.second,
-                                         [&status, &streamId](Status s, auto stream_id) {
-                                             status = s;
-                                             streamId = stream_id;
-                                         });
-        CHECK_TRANSACTION_AND_RET(ret, status, "createStream()")
-        mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
+    for (const auto &anw : addSet) {
+        int32_t streamId;
+        auto itr = handleToConfig.find(anw);
+        remoteRet = mRemote->createStream(itr->second, &streamId);
+        CHECK_TRANSACTION_AND_RET(remoteRet, "createStream()")
+        mConfiguredOutputs.insert(std::make_pair(streamId,
+                                                 std::make_pair(anw,
+                                                                std::move(itr->second))));
+        handleToConfig.erase(itr);
     }
 
-    CameraMetadata params;
-    HCameraMetadata hidlParams;
+    AidlCameraMetadata aidlParams;
     if ((sessionParameters != nullptr) && (sessionParameters->settings != nullptr)) {
-        params.append(sessionParameters->settings->getInternalData());
-        const camera_metadata_t *params_metadata = params.getAndLock();
-        utils::convertToHidl(params_metadata, &hidlParams);
-        params.unlock(params_metadata);
+        const CameraMetadata &params = sessionParameters->settings->getInternalData();
+        const camera_metadata_t* paramsMetadata = params.getAndLock();
+        utils::convertToAidl(paramsMetadata, &aidlParams);
+        params.unlock(paramsMetadata);
     }
-    remoteRet = mRemote->endConfigure_2_1(StreamConfigurationMode::NORMAL_MODE,
-                                          hidlParams, startTimeNs);
-    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "endConfigure()")
+    remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE,
+                                      aidlParams, startTimeNs);
+    CHECK_TRANSACTION_AND_RET(remoteRet, "endConfigure()")
     return ACAMERA_OK;
 }
 
-void
-CameraDevice::setRemoteDevice(sp<ICameraDeviceUser> remote) {
+void CameraDevice::setRemoteDevice(std::shared_ptr<ICameraDeviceUser> remote) {
     Mutex::Autolock _l(mDeviceLock);
-    mRemote = remote;
+    mRemote = std::move(remote);
 }
 
-bool
-CameraDevice::setDeviceMetadataQueues() {
+bool CameraDevice::setDeviceMetadataQueues() {
         if (mRemote == nullptr) {
           ALOGE("mRemote must not be null while trying to fetch metadata queues");
           return false;
         }
         std::shared_ptr<RequestMetadataQueue> &reqQueue = mCaptureRequestMetadataQueue;
-        auto ret =
-            mRemote->getCaptureRequestMetadataQueue(
-                [&reqQueue](const auto &mqDescriptor) {
-                    reqQueue = std::make_shared<RequestMetadataQueue>(mqDescriptor);
-                    if (!reqQueue->isValid() || reqQueue->availableToWrite() <=0) {
-                        ALOGE("Empty fmq from cameraserver");
-                        reqQueue = nullptr;
-                    }
-                });
+        MQDescriptor<int8_t, SynchronizedReadWrite> reqMqDescriptor;
+        ScopedAStatus ret = mRemote->getCaptureRequestMetadataQueue(&reqMqDescriptor);
         if (!ret.isOk()) {
             ALOGE("Transaction error trying to get capture request metadata queue");
             return false;
         }
+        reqQueue = std::make_shared<RequestMetadataQueue>(reqMqDescriptor);
+        if (!reqQueue->isValid() || reqQueue->availableToWrite() <= 0) {
+            ALOGE("Empty fmq from cameraserver");
+            reqQueue = nullptr;
+        }
+
+        MQDescriptor<int8_t, SynchronizedReadWrite> resMqDescriptor;
         std::shared_ptr<ResultMetadataQueue> &resQueue = mCaptureResultMetadataQueue;
-        ret =
-                mRemote->getCaptureResultMetadataQueue(
-                        [&resQueue](const auto &mqDescriptor) {
-                            resQueue = std::make_shared<ResultMetadataQueue>(mqDescriptor);
-                            if (!resQueue->isValid() || resQueue->availableToWrite() <=0) {
-                                ALOGE("Empty fmq from cameraserver");
-                            }
-                        });
+        ret = mRemote->getCaptureResultMetadataQueue(&resMqDescriptor);
         if (!ret.isOk()) {
             ALOGE("Transaction error trying to get capture result metadata queue");
             return false;
         }
+        resQueue = std::make_shared<ResultMetadataQueue>(resMqDescriptor);
+        if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+            ALOGE("Empty fmq from cameraserver");
+        }
+
         return true;
 }
 
-camera_status_t
-CameraDevice::checkCameraClosedOrErrorLocked() const {
+camera_status_t CameraDevice::checkCameraClosedOrErrorLocked() const {
     if (mRemote == nullptr) {
         ALOGE("%s: camera device already closed", __FUNCTION__);
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
-    if (mInError) {// triggered by onDeviceError
-        ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
+    if (mInError) { // triggered by onDeviceError
+        ALOGE("%s: camera device has encountered a serious error: %d", __FUNCTION__, mError);
         return mError;
     }
     return ACAMERA_OK;
 }
 
-void
-CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
+void CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
     mInError = true;
     mError = error;
-    return;
 }
 
-void
-CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
+void CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
     ALOGV("updateTracker frame %" PRId64 " isError %d", frameNumber, isError);
     if (isError) {
         mFutureErrorSet.insert(frameNumber);
@@ -791,8 +783,7 @@
     update();
 }
 
-void
-CameraDevice::FrameNumberTracker::update() {
+void CameraDevice::FrameNumberTracker::update() {
     for (auto it = mFutureErrorSet.begin(); it != mFutureErrorSet.end();) {
         int64_t errorFrameNumber = *it;
         if (errorFrameNumber == mCompletedFrameNumber + 1) {
@@ -811,10 +802,8 @@
     ALOGV("Update complete frame %" PRId64, mCompletedFrameNumber);
 }
 
-void
-CameraDevice::onCaptureErrorLocked(
-        ErrorCode errorCode,
-        const CaptureResultExtras& resultExtras) {
+void CameraDevice::onCaptureErrorLocked(ErrorCode errorCode,
+                                        const CaptureResultExtras& resultExtras) {
     int sequenceId = resultExtras.requestId;
     int64_t frameNumber = resultExtras.frameNumber;
     int32_t burstId = resultExtras.burstId;
@@ -826,7 +815,7 @@
         return;
     }
 
-    CallbackHolder cbh = (*it).second;
+    CallbackHolder cbh = it->second;
     sp<ACameraCaptureSession> session = cbh.mSession;
     if ((size_t) burstId >= cbh.mRequests.size()) {
         ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -852,7 +841,7 @@
         // them and try to match the surfaces in the corresponding
         // CaptureRequest.
         const auto& errorWindowHandles =
-                outputPairIt->second.second.mOutputConfiguration.windowHandles;
+                outputPairIt->second.second.windowHandles;
         for (const auto& errorWindowHandle : errorWindowHandles) {
             for (const auto &requestStreamAndWindowId :
                         request->mCaptureRequest.streamAndWindowIds) {
@@ -869,11 +858,11 @@
                 }
 
                 const auto &requestWindowHandles =
-                        requestSurfacePairIt->second.second.mOutputConfiguration.windowHandles;
-                if (utils::isWindowNativeHandleEqual(
-                        requestWindowHandles[requestWindowId], errorWindowHandle)) {
-                    const native_handle_t* anw =
-                            requestWindowHandles[requestWindowId].getNativeHandle();
+                        requestSurfacePairIt->second.second.windowHandles;
+
+                if (requestWindowHandles[requestWindowId] == errorWindowHandle) {
+                    const native_handle_t* anw = makeFromAidl(
+                            requestWindowHandles[requestWindowId]);
                     ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
                             getId(), anw, frameNumber);
 
@@ -898,14 +887,16 @@
         failure->sequenceId  = sequenceId;
         failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
 
-        sp<AMessage> msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail :
-                kWhatCaptureFail, mHandler);
+        sp<AMessage> msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail
+                                                                     : kWhatCaptureFail,
+                                        mHandler);
         msg->setPointer(kContextKey, cbh.mContext);
         msg->setObject(kSessionSpKey, session);
         if (cbh.mIsLogicalCameraCallback) {
-            if (resultExtras.errorPhysicalCameraId.size() > 0) {
-                msg->setString(kFailingPhysicalCameraId, resultExtras.errorPhysicalCameraId.c_str(),
-                        resultExtras.errorPhysicalCameraId.size());
+            if (!resultExtras.errorPhysicalCameraId.empty()) {
+                msg->setString(kFailingPhysicalCameraId,
+                               resultExtras.errorPhysicalCameraId.c_str(),
+                               resultExtras.errorPhysicalCameraId.size());
             }
             msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
         } else {
@@ -919,7 +910,6 @@
         mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
         checkAndFireSequenceCompleteLocked();
     }
-    return;
 }
 
 CameraDevice::CallbackHandler::CallbackHandler(const char *id) : mId(id) { }
@@ -1020,7 +1010,7 @@
                 return;
             }
             sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
-            mCachedSessions.push(session);
+            mCachedSessions.push_back(session);
             sp<CaptureRequest> requestSp = nullptr;
             const char *id_cstr = mId.c_str();
             switch (msg->what()) {
@@ -1167,7 +1157,8 @@
                         clone.update(ANDROID_SYNC_FRAME_NUMBER,
                                 &physicalResult->mFrameNumber, /*data_count*/1);
                         sp<ACameraMetadata> metadata =
-                                new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+                                new ACameraMetadata(clone.release(),
+                                                    ACameraMetadata::ACM_RESULT);
                         physicalMetadataCopy.push_back(metadata);
                     }
                     std::vector<const char*> physicalCameraIdPtrs;
@@ -1302,7 +1293,7 @@
                         return;
                     }
 
-                    const native_handle_t* anw;
+                    native_handle_t* anw;
                     found = msg->findPointer(kAnwKey, (void**) &anw);
                     if (!found) {
                         ALOGE("%s: Cannot find native_handle_t!", __FUNCTION__);
@@ -1319,6 +1310,7 @@
                     ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
                     (*onBufferLost)(context, session.get(), request, anw, frameNumber);
                     freeACaptureRequest(request);
+                    native_handle_delete(anw); // clean up anw as it was copied from AIDL
                     break;
                 }
             }
@@ -1329,10 +1321,10 @@
 
 CameraDevice::CallbackHolder::CallbackHolder(
         sp<ACameraCaptureSession>          session,
-        const Vector<sp<CaptureRequest> >& requests,
+        std::vector<sp<CaptureRequest>>  requests,
         bool                               isRepeating,
         ACameraCaptureSession_captureCallbacks* cbs) :
-        mSession(session), mRequests(requests),
+        mSession(std::move(session)), mRequests(std::move(requests)),
         mIsRepeating(isRepeating),
         mIs2Callback(false),
         mIsLogicalCameraCallback(false) {
@@ -1346,10 +1338,10 @@
 
 CameraDevice::CallbackHolder::CallbackHolder(
         sp<ACameraCaptureSession>          session,
-        const Vector<sp<CaptureRequest> >& requests,
+        std::vector<sp<CaptureRequest>>  requests,
         bool                               isRepeating,
         ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
-        mSession(session), mRequests(requests),
+        mSession(std::move(session)), mRequests(std::move(requests)),
         mIsRepeating(isRepeating),
         mIs2Callback(false),
         mIsLogicalCameraCallback(true) {
@@ -1363,10 +1355,10 @@
 
 CameraDevice::CallbackHolder::CallbackHolder(
         sp<ACameraCaptureSession>          session,
-        const Vector<sp<CaptureRequest> >& requests,
+        std::vector<sp<CaptureRequest>>  requests,
         bool                               isRepeating,
         ACameraCaptureSession_captureCallbacksV2* cbs) :
-        mSession(session), mRequests(requests),
+        mSession(std::move(session)), mRequests(std::move(requests)),
         mIsRepeating(isRepeating),
         mIs2Callback(true),
         mIsLogicalCameraCallback(false) {
@@ -1380,10 +1372,10 @@
 
 CameraDevice::CallbackHolder::CallbackHolder(
         sp<ACameraCaptureSession>          session,
-        const Vector<sp<CaptureRequest> >& requests,
+        std::vector<sp<CaptureRequest>>  requests,
         bool                               isRepeating,
         ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs) :
-        mSession(session), mRequests(requests),
+        mSession(std::move(session)), mRequests(std::move(requests)),
         mIsRepeating(isRepeating),
         mIs2Callback(true),
         mIsLogicalCameraCallback(true) {
@@ -1501,23 +1493,21 @@
 /**
   * Camera service callback implementation
   */
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onDeviceError(
-        ErrorCode errorCode,
-        const CaptureResultExtras& resultExtras) {
+ScopedAStatus CameraDevice::ServiceCallback::onDeviceError(
+        ErrorCode errorCode, const CaptureResultExtras& resultExtras) {
     ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d"
             " physical camera ID %s", errorCode, resultExtras.frameNumber, resultExtras.requestId,
             resultExtras.burstId, resultExtras.errorPhysicalCameraId.c_str());
-    auto ret = Void();
-    sp<CameraDevice> dev = mDevice.promote();
+
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
     if (dev == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
 
     sp<ACameraCaptureSession> session = dev->mCurrentSession.promote();
     Mutex::Autolock _l(dev->mDeviceLock);
     if (dev->mRemote == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
     switch (errorCode) {
         case ErrorCode::CAMERA_DISCONNECTED:
@@ -1570,26 +1560,25 @@
             dev->onCaptureErrorLocked(errorCode, resultExtras);
             break;
     }
-    return ret;
+    return ScopedAStatus::ok();
 }
 
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onDeviceIdle() {
+ScopedAStatus CameraDevice::ServiceCallback::onDeviceIdle() {
     ALOGV("Camera is now idle");
-    auto ret = Void();
-    sp<CameraDevice> dev = mDevice.promote();
+
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
     if (dev == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
 
     Mutex::Autolock _l(dev->mDeviceLock);
     if (dev->isClosed() || dev->mRemote == nullptr) {
-        return ret;
+        return ScopedAStatus::ok();
     }
 
     if (dev->mIdle) {
         // Already in idle state. Possibly other thread did waitUntilIdle
-        return ret;
+        return ScopedAStatus::ok();
     }
 
     if (dev->mCurrentSession != nullptr) {
@@ -1597,13 +1586,14 @@
         if (dev->mBusySession != dev->mCurrentSession) {
             ALOGE("Current session != busy session");
             dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
-            return ret;
+            return ScopedAStatus::ok();
         }
 
         sp<AMessage> msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
         msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
         msg->setObject(kSessionSpKey, dev->mBusySession);
-        msg->setPointer(kCallbackFpKey, (void*) dev->mBusySession->mUserSessionCallback.onReady);
+        msg->setPointer(kCallbackFpKey,
+                        (void*) dev->mBusySession->mUserSessionCallback.onReady);
         // Make sure we clear the sp first so the session destructor can
         // only happen on handler thread (where we don't hold device/session lock)
         dev->mBusySession.clear();
@@ -1611,22 +1601,20 @@
     }
     dev->mIdle = true;
     dev->mFlushing = false;
-    return ret;
+    return ScopedAStatus::ok();
 }
 
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onCaptureStarted(
-        const CaptureResultExtras& resultExtras,
-        uint64_t timestamp) {
-    auto ret = Void();
 
-    sp<CameraDevice> dev = mDevice.promote();
+
+ndk::ScopedAStatus CameraDevice::ServiceCallback::onCaptureStarted(
+        const CaptureResultExtras& resultExtras, int64_t timestamp) {
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
     if (dev == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
     Mutex::Autolock _l(dev->mDeviceLock);
     if (dev->isClosed() || dev->mRemote == nullptr) {
-        return ret;
+        return ScopedAStatus::ok();
     }
 
     int32_t sequenceId = resultExtras.requestId;
@@ -1635,7 +1623,7 @@
 
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
-        CallbackHolder cbh = (*it).second;
+        CallbackHolder &cbh = it->second;
         ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
         ACameraCaptureSession_captureCallback_startV2 onStart2 = cbh.mOnCaptureStarted2;
         bool v2Callback = cbh.mIs2Callback;
@@ -1646,6 +1634,7 @@
             dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
         }
         sp<CaptureRequest> request = cbh.mRequests[burstId];
+        ALOGE("%s: request = %p", __FUNCTION__, request.get());
         sp<AMessage> msg = nullptr;
         if (v2Callback) {
             msg = new AMessage(kWhatCaptureStart2, dev->mHandler);
@@ -1661,24 +1650,22 @@
         msg->setInt64(kFrameNumberKey, frameNumber);
         dev->postSessionMsgAndCleanup(msg);
     }
-    return ret;
+    return ScopedAStatus::ok();
 }
 
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onResultReceived(
-        const FmqSizeOrMetadata& resultMetadata,
+ScopedAStatus CameraDevice::ServiceCallback::onResultReceived(
+        const CaptureMetadataInfo& resultMetadata,
         const CaptureResultExtras& resultExtras,
-        const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) {
-    auto ret = Void();
+        const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
 
-    sp<CameraDevice> dev = mDevice.promote();
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
     if (dev == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
     int32_t sequenceId = resultExtras.requestId;
     int64_t frameNumber = resultExtras.frameNumber;
     int32_t burstId = resultExtras.burstId;
-    bool    isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
+    bool isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
 
     if (!isPartialResult) {
         ALOGV("SeqId %d frame %" PRId64 " result arrive.", sequenceId, frameNumber);
@@ -1686,7 +1673,7 @@
 
     Mutex::Autolock _l(dev->mDeviceLock);
     if (dev->mRemote == nullptr) {
-        return ret; // device has been disconnected
+        return ScopedAStatus::ok(); // device has been disconnected
     }
 
     if (dev->isClosed()) {
@@ -1694,7 +1681,7 @@
             dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
         }
         // early return to avoid callback sent to closed devices
-        return ret;
+        return ScopedAStatus::ok();
     }
 
     CameraMetadata metadataCopy;
@@ -1702,11 +1689,12 @@
             dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
     if (status != ACAMERA_OK) {
         ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
-        return ret;
+        return ScopedAStatus::ok();
     }
 
-    metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize, /*data_count*/2);
-    metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /*data_count*/1);
+    metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize,
+                        /* data_count= */ 2);
+    metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /* data_count= */1);
 
     auto it = dev->mSequenceCallbackMap.find(sequenceId);
     if (it != dev->mSequenceCallbackMap.end()) {
@@ -1730,7 +1718,7 @@
                     &localPhysicalResult[i].physicalMetadata);
             if (status != ACAMERA_OK) {
                 ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
-                return ret;
+                return ScopedAStatus::ok();
             }
         }
         sp<ACameraPhysicalCaptureResultInfo> physicalResult(
@@ -1762,17 +1750,14 @@
         dev->checkAndFireSequenceCompleteLocked();
     }
 
-    return ret;
+    return ScopedAStatus::ok();
 }
 
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onRepeatingRequestError(
-        uint64_t lastFrameNumber, int32_t stoppedSequenceId) {
-    auto ret = Void();
-
-    sp<CameraDevice> dev = mDevice.promote();
+ScopedAStatus CameraDevice::ServiceCallback::onRepeatingRequestError(int64_t lastFrameNumber,
+                                                                     int32_t stoppedSequenceId) {
+    std::shared_ptr<CameraDevice> dev = mDevice.lock();
     if (dev == nullptr) {
-        return ret; // device has been closed
+        return ScopedAStatus::ok(); // device has been closed
     }
 
     Mutex::Autolock _l(dev->mDeviceLock);
@@ -1784,33 +1769,41 @@
 
     dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
 
-    return ret;
+    return ScopedAStatus::ok();
 }
 
 camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
-        const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+        const CaptureMetadataInfo& captureMetadataInfo, ResultMetadataQueue* metadataQueue,
         CameraMetadata* metadata) {
     if (metadataQueue == nullptr || metadata == nullptr) {
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
     bool converted;
-    HCameraMetadata hCameraMetadata;
-    if (fmqSizeOrMetadata.getDiscriminator() ==
-            FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
-        hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
-        bool read = metadataQueue->read(
-                hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+    AidlCameraMetadata aidlCameraMetadata;
+    std::vector<uint8_t>& metadataVec = aidlCameraMetadata.metadata;
+    camera_metadata_t* clonedMetadata;
+    if (captureMetadataInfo.getTag() == CaptureMetadataInfo::fmqMetadataSize) {
+        int64_t size = captureMetadataInfo.get<CaptureMetadataInfo::fmqMetadataSize>();
+        metadataVec.resize(size);
+        bool read = metadataQueue->read(reinterpret_cast<int8_t*>(metadataVec.data()), size);
         if (!read) {
             ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
             return ACAMERA_ERROR_UNKNOWN;
         }
         // TODO: Do we actually need to clone here ?
-        converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+        converted = utils::cloneFromAidl(aidlCameraMetadata, &clonedMetadata);
     } else {
-        converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+        const AidlCameraMetadata &embeddedMetadata =
+                captureMetadataInfo.get<CaptureMetadataInfo::metadata>();
+        converted = utils::cloneFromAidl(embeddedMetadata, &clonedMetadata);
     }
 
-    return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+    if (converted) {
+        *metadata = CameraMetadata(clonedMetadata);
+        return ACAMERA_OK;
+    }
+
+    return ACAMERA_ERROR_UNKNOWN;
 }
 
 } // namespace acam
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index c306206..cad23aa 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -16,54 +16,63 @@
 #ifndef _ACAMERA_DEVICE_H
 #define _ACAMERA_DEVICE_H
 
-#include <memory>
-#include <map>
-#include <set>
-#include <atomic>
-#include <utility>
-#include <vector>
-#include <utils/StrongPointer.h>
-#include <utils/Mutex.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <android/frameworks/cameraservice/device/2.1/ICameraDeviceUser.h>
-#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceCallback.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <fmq/MessageQueue.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <camera/NdkCameraManager.h>
-#include <camera/NdkCameraCaptureSession.h>
-
 #include "ACameraMetadata.h"
 #include "utils.h"
 
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceCallback.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureResultExtras.h>
+#include <aidl/android/frameworks/cameraservice/device/ErrorCode.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/ICameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <atomic>
+#include <camera/NdkCameraCaptureSession.h>
+#include <camera/NdkCameraManager.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/MessageQueue.h>
+#include <map>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <memory>
+#include <set>
+#include <utility>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+#include <vector>
+
 namespace android {
 namespace acam {
 
-using ICameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback;
-using ICameraDeviceUser_2_0 = frameworks::cameraservice::device::V2_0::ICameraDeviceUser;
-using ICameraDeviceUser = frameworks::cameraservice::device::V2_1::ICameraDeviceUser;
-using CaptureResultExtras = frameworks::cameraservice::device::V2_0::CaptureResultExtras;
-using PhysicalCaptureResultInfo = frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo;
-using PhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
-using SubmitInfo = frameworks::cameraservice::device::V2_0::SubmitInfo;
-using CaptureResultExtras = frameworks::cameraservice::device::V2_0::CaptureResultExtras;
-using ErrorCode = frameworks::cameraservice::device::V2_0::ErrorCode;
-using FmqSizeOrMetadata = frameworks::cameraservice::device::V2_0::FmqSizeOrMetadata;
-using StreamConfigurationMode = frameworks::cameraservice::device::V2_0::StreamConfigurationMode;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::device::BnCameraDeviceCallback;
+using ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using ::aidl::android::frameworks::cameraservice::device::ErrorCode;
+using ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+using ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::acam::utils::native_handle_ptr_wrapper;
 
-using hardware::hidl_vec;
-using hardware::hidl_string;
-using utils::native_handle_ptr_wrapper;
+
+using ResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+using RequestMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
 using utils::CaptureRequest;
-using utils::OutputConfigurationWrapper;
 
 // Wrap ACameraCaptureFailure so it can be ref-counted
 struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { };
@@ -83,13 +92,16 @@
     int64_t mFrameNumber;
 };
 
-class CameraDevice final : public RefBase {
+class CameraDevice final : public std::enable_shared_from_this<CameraDevice> {
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
                   sp<ACameraMetadata> chars,
                   ACameraDevice* wrapper);
     ~CameraDevice();
 
+    // Called to initialize fields that require shared_ptr to `this`
+    void init();
+
     inline const char* getId() const { return mCameraId.c_str(); }
 
     camera_status_t createCaptureRequest(
@@ -107,30 +119,35 @@
             const ACaptureSessionOutputContainer* sessionOutputContainer) const;
 
     // Callbacks from camera service
-    class ServiceCallback : public ICameraDeviceCallback {
+    class ServiceCallback : public BnCameraDeviceCallback {
       public:
-        explicit ServiceCallback(CameraDevice* device) : mDevice(device) {}
-        android::hardware::Return<void> onDeviceError(ErrorCode errorCode,
-                           const CaptureResultExtras& resultExtras) override;
-        android::hardware::Return<void> onDeviceIdle() override;
-        android::hardware::Return<void> onCaptureStarted(const CaptureResultExtras& resultExtras,
-                              uint64_t timestamp) override;
-        android::hardware::Return<void> onResultReceived(const FmqSizeOrMetadata& result,
-                              const CaptureResultExtras& resultExtras,
-                              const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) override;
-        android::hardware::Return<void> onRepeatingRequestError(uint64_t lastFrameNumber,
-                int32_t stoppedSequenceId) override;
+        explicit ServiceCallback(std::weak_ptr<CameraDevice> device) :
+              mDevice(std::move(device)) {}
+
+        ndk::ScopedAStatus onDeviceError(ErrorCode in_errorCode,
+                                         const CaptureResultExtras& in_resultExtras) override;
+        ndk::ScopedAStatus onDeviceIdle() override;
+
+        ndk::ScopedAStatus onCaptureStarted(const CaptureResultExtras& in_resultExtras,
+                                            int64_t in_timestamp) override;
+        ndk::ScopedAStatus onRepeatingRequestError(int64_t in_lastFrameNumber,
+                                                   int32_t in_repeatingRequestId) override;
+        ndk::ScopedAStatus onResultReceived(const CaptureMetadataInfo& in_result,
+                                            const CaptureResultExtras& in_resultExtras,
+                                            const std::vector<PhysicalCaptureResultInfo>&
+                                                    in_physicalCaptureResultInfos) override;
+
       private:
-        camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata,
+        camera_status_t readOneResultMetadata(const CaptureMetadataInfo& captureMetadataInfo,
                 ResultMetadataQueue* metadataQueue, CameraMetadata* metadata);
-        const wp<CameraDevice> mDevice;
+        const std::weak_ptr<CameraDevice> mDevice;
     };
-    inline sp<ICameraDeviceCallback> getServiceCallback() {
+    inline std::shared_ptr<BnCameraDeviceCallback> getServiceCallback() {
         return mServiceCallback;
     };
 
     // Camera device is only functional after remote being set
-    void setRemoteDevice(sp<ICameraDeviceUser> remote);
+    void setRemoteDevice(std::shared_ptr<ICameraDeviceUser> remote);
 
     bool setDeviceMetadataQueues();
     inline ACameraDevice* getWrapper() const { return mWrapper; };
@@ -208,15 +225,15 @@
     void postSessionMsgAndCleanup(sp<AMessage>& msg);
 
     mutable Mutex mDeviceLock;
-    const hidl_string mCameraId;                          // Camera ID
+    const std::string mCameraId;                          // Camera ID
     const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
     const sp<ACameraMetadata> mChars;    // Camera characteristics
-    const sp<ServiceCallback> mServiceCallback;
+    std::shared_ptr<ServiceCallback> mServiceCallback;
     ACameraDevice* mWrapper;
 
     // stream id -> pair of (ACameraWindowType* from application, OutputConfiguration used for
     // camera service)
-    std::map<int, std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> mConfiguredOutputs;
+    std::map<int, std::pair<native_handle_ptr_wrapper, OutputConfiguration>> mConfiguredOutputs;
 
     // TODO: maybe a bool will suffice for synchronous implementation?
     std::atomic_bool mClosing;
@@ -232,7 +249,7 @@
     // This will avoid a busy session being deleted before it's back to idle state
     sp<ACameraCaptureSession> mBusySession;
 
-    sp<ICameraDeviceUser> mRemote;
+    std::shared_ptr<ICameraDeviceUser> mRemote;
 
     // Looper thread to handle callback to app
     sp<ALooper> mCbLooper;
@@ -281,7 +298,7 @@
         // This handler will cache all capture session sp until kWhatCleanUpSessions
         // is processed. This is used to guarantee the last session reference is always
         // being removed in callback thread without holding camera device lock
-        Vector<sp<ACameraCaptureSession>> mCachedSessions;
+        std::vector<sp<ACameraCaptureSession>> mCachedSessions;
     };
     sp<CallbackHandler> mHandler;
 
@@ -303,19 +320,19 @@
 
     struct CallbackHolder {
         CallbackHolder(sp<ACameraCaptureSession>          session,
-                       const Vector<sp<CaptureRequest>>&  requests,
+                       std::vector<sp<CaptureRequest>>   requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_captureCallbacks* cbs);
         CallbackHolder(sp<ACameraCaptureSession>          session,
-                       const Vector<sp<CaptureRequest>>&  requests,
+                       std::vector<sp<CaptureRequest>>   requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
         CallbackHolder(sp<ACameraCaptureSession>          session,
-                       const Vector<sp<CaptureRequest> >& requests,
+                       std::vector<sp<CaptureRequest> >  requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_captureCallbacksV2* cbs);
         CallbackHolder(sp<ACameraCaptureSession>          session,
-                       const Vector<sp<CaptureRequest> >& requests,
+                       std::vector<sp<CaptureRequest> >  requests,
                        bool                               isRepeating,
                        ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs);
         void clearCallbacks() {
@@ -359,7 +376,7 @@
         }
 
         sp<ACameraCaptureSession>   mSession;
-        Vector<sp<CaptureRequest>>  mRequests;
+        std::vector<sp<CaptureRequest>>  mRequests;
         const bool                  mIsRepeating;
         const bool                  mIs2Callback;
         const bool                  mIsLogicalCameraCallback;
@@ -401,7 +418,7 @@
     // Misc variables
     int32_t mShadingMapSize[2];   // const after constructor
     int32_t mPartialResultCount;  // const after constructor
-    std::shared_ptr<ResultMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
+    std::shared_ptr<RequestMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
     std::shared_ptr<ResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
 };
 
@@ -415,7 +432,10 @@
 struct ACameraDevice {
     ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
                   sp<ACameraMetadata> chars) :
-            mDevice(new android::acam::CameraDevice(id, cb, std::move(chars), this)) {}
+            mDevice(std::make_shared<android::acam::CameraDevice>(id, cb,
+                                                                std::move(chars), this)) {
+        mDevice->init();
+    }
 
     ~ACameraDevice();
     /*******************
@@ -446,19 +466,20 @@
     /***********************
      * Device interal APIs *
      ***********************/
-    inline android::sp<android::acam::ICameraDeviceCallback> getServiceCallback() {
+    inline std::shared_ptr<android::acam::BnCameraDeviceCallback> getServiceCallback() {
         return mDevice->getServiceCallback();
     };
 
     // Camera device is only functional after remote being set
-    inline void setRemoteDevice(android::sp<android::acam::ICameraDeviceUser> remote) {
+    inline void setRemoteDevice(std::shared_ptr<
+            ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser> remote) {
         mDevice->setRemoteDevice(remote);
     }
     inline bool setDeviceMetadataQueues() {
         return mDevice->setDeviceMetadataQueues();
     }
   private:
-    android::sp<android::acam::CameraDevice> mDevice;
+    std::shared_ptr<android::acam::CameraDevice> mDevice;
 };
 
 #endif // _ACAMERA_DEVICE_H
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
index 8bd5a52..1e724eb 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -14,17 +14,14 @@
  * limitations under the License.
  */
 
-#include <vector>
-#include <inttypes.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <CameraMetadata.h>
-
-#include "ndk_vendor/impl/ACameraDevice.h"
 #include "ACameraCaptureSession.h"
 #include "ACameraMetadata.h"
 #include "ACaptureRequest.h"
 #include "utils.h"
+#include <CameraMetadata.h>
+#include <inttypes.h>
+#include <ndk_vendor/impl/ACameraDevice.h>
+#include <vector>
 
 using namespace android;
 
@@ -32,22 +29,22 @@
 namespace acam {
 
 template<class T>
-camera_status_t
-CameraDevice::captureLocked(
+camera_status_t CameraDevice::captureLocked(
         sp<ACameraCaptureSession> session,
         /*optional*/T* cbs,
-        int numRequests, ACaptureRequest** requests,
+        int numRequests,
+        ACaptureRequest** requests,
         /*optional*/int* captureSequenceId) {
     return submitRequestsLocked(
             session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
 }
 
 template<class T>
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
+camera_status_t CameraDevice::setRepeatingRequestsLocked(
         sp<ACameraCaptureSession> session,
         /*optional*/T* cbs,
-        int numRequests, ACaptureRequest** requests,
+        int numRequests,
+        ACaptureRequest** requests,
         /*optional*/int* captureSequenceId) {
     return submitRequestsLocked(
             session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
@@ -56,11 +53,10 @@
 template<class T>
 camera_status_t CameraDevice::submitRequestsLocked(
         sp<ACameraCaptureSession> session,
-        /*optional*/T* cbs,
-        int numRequests, ACaptureRequest** requests,
+        /*optional*/T* cbs, int numRequests,
+        ACaptureRequest** requests,
         /*out*/int* captureSequenceId,
-        bool isRepeating)
-{
+        bool isRepeating) {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
         ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
@@ -68,9 +64,10 @@
     }
 
     // Form two vectors of capture request, one for internal tracking
-    std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
-    Vector<sp<CaptureRequest>> requestsV;
-    requestsV.setCapacity(numRequests);
+
+    std::vector<::aidl::android::frameworks::cameraservice::device::CaptureRequest> requestList;
+    std::vector<sp<CaptureRequest>> requestsV;
+    requestsV.reserve(numRequests);
     for (int i = 0; i < numRequests; i++) {
         sp<CaptureRequest> req;
         ret = allocateCaptureRequestLocked(requests[i], req);
@@ -87,7 +84,7 @@
             ALOGE("Capture request without output target cannot be submitted!");
             return ACAMERA_ERROR_INVALID_PARAMETER;
         }
-        requestList.push_back(utils::convertToHidl(req.get()));
+        requestList.push_back(utils::convertToAidl(req.get()));
         requestsV.push_back(req);
     }
     if (isRepeating) {
@@ -100,18 +97,20 @@
 
     SubmitInfo info;
     Status status;
-    auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
-                                                [&status, &info](auto s, auto &submitInfo) {
-                                                    status = s;
-                                                    info = submitInfo;
-                                                });
-    if (!remoteRet.isOk()) {
-        ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
-              remoteRet.description().c_str());
+    ndk::ScopedAStatus remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+        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;
+        }
     }
-    if (status != Status::NO_ERROR) {
-        return utils::convertFromHidl(status);
-    }
+
     int32_t sequenceId = info.requestId;
     int64_t lastFrameNumber = info.lastFrameNumber;
     if (sequenceId < 0) {
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index bb4ef56..3aa7817 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -17,28 +17,29 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ACameraManagerVendor"
 
-#include <memory>
-#include "ndk_vendor/impl/ACameraManager.h"
 #include "ACameraMetadata.h"
 #include "ndk_vendor/impl/ACameraDevice.h"
+#include "ndk_vendor/impl/ACameraManager.h"
 #include "utils.h"
+
 #include <CameraMetadata.h>
-#include <camera_metadata_hidden.h>
-
-#include <utils/Vector.h>
-#include <cutils/properties.h>
-#include <stdlib.h>
-
 #include <VendorTagDescriptor.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <camera_metadata_hidden.h>
+#include <cutils/properties.h>
+#include <memory>
+#include <utils/Vector.h>
 
 using namespace android::acam;
 
 namespace android {
 namespace acam {
 
-using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
-using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
-using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ::aidl::android::frameworks::cameraservice::common::ProviderIdAndVendorTagSections;
+using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
+using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ::ndk::ScopedAStatus;
 
 // Static member definitions
 const char* CameraManagerGlobal::kCameraIdKey   = "CameraId";
@@ -47,52 +48,55 @@
 const char* CameraManagerGlobal::kContextKey    = "CallbackContext";
 const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
 Mutex                CameraManagerGlobal::sLock;
-CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+std::weak_ptr<CameraManagerGlobal> CameraManagerGlobal::sInstance =
+        std::weak_ptr<CameraManagerGlobal>();
 
 /**
- * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * The vendor tag descriptor class that takes AIDL vendor tag information as
  * input. Not part of vendor available VendorTagDescriptor class because that class is used by
  * default HAL implementation code as well.
+ *
+ * This is a class instead of a free-standing function because VendorTagDescriptor has some
+ * protected fields that need to be initialized during conversion.
  */
-class HidlVendorTagDescriptor : public VendorTagDescriptor {
+class AidlVendorTagDescriptor : public VendorTagDescriptor {
 public:
     /**
-     * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+     * Create a VendorTagDescriptor object from the AIDL VendorTagSection
      * vector.
      *
      * Returns OK on success, or a negative error code.
      */
-    static status_t createDescriptorFromHidl(const hidl_vec<VendorTagSection>& vts,
+    static status_t createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
                                              /*out*/ sp<VendorTagDescriptor> *descriptor);
 };
 
-status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec<VendorTagSection> &vts,
-                                                           sp<VendorTagDescriptor> *descriptor) {
-    int tagCount = 0;
+status_t AidlVendorTagDescriptor::createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
+                                                           sp<VendorTagDescriptor>* descriptor){
+    size_t tagCount = 0;
 
     for (size_t s = 0; s < vts.size(); s++) {
         tagCount += vts[s].tags.size();
     }
 
     if (tagCount < 0 || tagCount > INT32_MAX) {
-        ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
+        ALOGE("%s: tag count %zu from vendor tag sections is invalid.", __FUNCTION__, tagCount);
         return BAD_VALUE;
     }
 
-    Vector<uint32_t> tagArray;
-    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
-            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+    std::vector<int64_t> tagArray;
+    tagArray.resize(tagCount);
 
-    sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+    sp<AidlVendorTagDescriptor> desc = new AidlVendorTagDescriptor();
     desc->mTagCount = tagCount;
 
-    KeyedVector<uint32_t, String8> tagToSectionMap;
+    std::map<int64_t, std::string> tagToSectionMap;
 
     int idx = 0;
     for (size_t s = 0; s < vts.size(); s++) {
         const VendorTagSection& section = vts[s];
         const char *sectionName = section.sectionName.c_str();
-        if (sectionName == NULL) {
+        if (sectionName == nullptr) {
             ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
             return BAD_VALUE;
         }
@@ -106,15 +110,15 @@
                 return BAD_VALUE;
             }
 
-            tagArray.editItemAt(idx++) = section.tags[j].tagId;
+            tagArray[idx++] = section.tags[j].tagId;
 
             const char *tagName = section.tags[j].tagName.c_str();
-            if (tagName == NULL) {
+            if (tagName == nullptr) {
                 ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
                 return BAD_VALUE;
             }
             desc->mTagToNameMap.add(tag, String8(tagName));
-            tagToSectionMap.add(tag, sectionString);
+            tagToSectionMap.insert({tag, section.sectionName});
 
             int tagType = (int) section.tags[j].tagType;
             if (tagType < 0 || tagType >= NUM_TYPES) {
@@ -127,8 +131,12 @@
 
     for (size_t i = 0; i < tagArray.size(); ++i) {
         uint32_t tag = tagArray[i];
-        String8 sectionString = tagToSectionMap.valueFor(tag);
-
+        auto itr = tagToSectionMap.find(tag);
+        if (itr == tagToSectionMap.end()) {
+            ALOGE("%s: Couldn't find previously added tag in map.", __FUNCTION__);
+            return UNKNOWN_ERROR;
+        }
+        String8 sectionString = String8(itr->second.c_str());
         // Set up tag to section index map
         ssize_t index = desc->mSections.indexOf(sectionString);
         LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
@@ -147,38 +155,37 @@
     return OK;
 }
 
-CameraManagerGlobal&
-CameraManagerGlobal::getInstance() {
+std::shared_ptr<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
     Mutex::Autolock _l(sLock);
-    CameraManagerGlobal* instance = sInstance;
+    std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
     if (instance == nullptr) {
-        instance = new CameraManagerGlobal();
+        instance = std::make_shared<CameraManagerGlobal>();
         sInstance = instance;
     }
-    return *instance;
+    return instance;
 }
 
 CameraManagerGlobal::~CameraManagerGlobal() {
-    // clear sInstance so next getInstance call knows to create a new one
     Mutex::Autolock _sl(sLock);
-    sInstance = nullptr;
     Mutex::Autolock _l(mLock);
     if (mCameraService != nullptr) {
-        mCameraService->unlinkToDeath(mDeathNotifier);
+        AIBinder_unlinkToDeath(mCameraService->asBinder().get(),
+                               mDeathRecipient.get(), this);
         auto stat = mCameraService->removeListener(mCameraServiceListener);
         if (!stat.isOk()) {
-            ALOGE("Failed to remove listener to camera service %s", stat.description().c_str());
+            ALOGE("Failed to remove listener to camera service %d:%d", stat.getExceptionCode(),
+                  stat.getServiceSpecificError());
         }
     }
-    mDeathNotifier.clear();
+
     if (mCbLooper != nullptr) {
         mCbLooper->unregisterHandler(mHandler->id());
         mCbLooper->stop();
     }
     mCbLooper.clear();
     mHandler.clear();
-    mCameraServiceListener.clear();
-    mCameraService.clear();
+    mCameraServiceListener.reset();
+    mCameraService.reset();
 }
 
 static bool isCameraServiceDisabled() {
@@ -191,23 +198,28 @@
     sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
     Status status = Status::NO_ERROR;
     std::vector<ProviderIdAndVendorTagSections> providerIdsAndVts;
-    auto remoteRet = mCameraService->getCameraVendorTagSections([&status, &providerIdsAndVts]
-                                                                 (Status s,
-                                                                  auto &IdsAndVts) {
-                                                         status = s;
-                                                         providerIdsAndVts = IdsAndVts; });
+    ScopedAStatus remoteRet = mCameraService->getCameraVendorTagSections(&providerIdsAndVts);
 
-    if (!remoteRet.isOk() || status != Status::NO_ERROR) {
-        ALOGE("Failed to retrieve VendorTagSections %s", remoteRet.description().c_str());
+    if (!remoteRet.isOk()) {
+        if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+            ALOGE("%s: Failed to retrieve VendorTagSections %s",
+                __FUNCTION__, toString(status).c_str());
+        } else {
+            ALOGE("%s: Binder error when retrieving VendorTagSections: %d", __FUNCTION__,
+                remoteRet.getExceptionCode());
+        }
         return false;
     }
+
     // Convert each providers VendorTagSections into a VendorTagDescriptor and
     // add it to the cache
     for (auto &providerIdAndVts : providerIdsAndVts) {
         sp<VendorTagDescriptor> vendorTagDescriptor;
-        if (HidlVendorTagDescriptor::createDescriptorFromHidl(providerIdAndVts.vendorTagSections,
-                                                              &vendorTagDescriptor) != OK) {
-            ALOGE("Failed to convert from Hidl: VendorTagDescriptor");
+        status_t ret = AidlVendorTagDescriptor::createDescriptorFromAidl(
+                providerIdAndVts.vendorTagSections, &vendorTagDescriptor);
+        if (ret != OK) {
+            ALOGE("Failed to convert from Aidl: VendorTagDescriptor: %d", ret);
             return false;
         }
         tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor);
@@ -216,101 +228,125 @@
     return true;
 }
 
-sp<ICameraService> CameraManagerGlobal::getCameraService() {
+std::shared_ptr<ICameraService> CameraManagerGlobal::getCameraService() {
     Mutex::Autolock _l(mLock);
-    if (mCameraService.get() == nullptr) {
-        if (isCameraServiceDisabled()) {
-            return mCameraService;
-        }
 
-        sp<ICameraService> cameraServiceBinder;
-        do {
-            cameraServiceBinder = ICameraService::getService();
-            if (cameraServiceBinder != nullptr) {
-                break;
-            }
-            ALOGW("CameraService not published, waiting...");
-            usleep(kCameraServicePollDelay);
-        } while(true);
-        if (mDeathNotifier == nullptr) {
-            mDeathNotifier = new DeathNotifier(this);
-        }
-        cameraServiceBinder->linkToDeath(mDeathNotifier, 0);
-        mCameraService = cameraServiceBinder;
+    if (mCameraService != nullptr) {
+        // Camera service already set up. Return existing value.
+        return mCameraService;
+    }
 
-        // Setup looper thread to perfrom availiability callbacks
-        if (mCbLooper == nullptr) {
-            mCbLooper = new ALooper;
-            mCbLooper->setName("C2N-mgr-looper");
-            status_t err = mCbLooper->start(
-                    /*runOnCallingThread*/false,
-                    /*canCallJava*/       true,
-                    PRIORITY_DEFAULT);
-            if (err != OK) {
-                ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
-                        __FUNCTION__, strerror(-err), err);
-                mCbLooper.clear();
-                return nullptr;
-            }
-            if (mHandler == nullptr) {
-                mHandler = new CallbackHandler(this);
-            }
-            mCbLooper->registerHandler(mHandler);
-        }
+    if (isCameraServiceDisabled()) {
+        // Camera service is disabled. return nullptr.
+        return mCameraService;
+    }
 
-        // register ICameraServiceListener
-        if (mCameraServiceListener == nullptr) {
-            mCameraServiceListener = new CameraServiceListener(this);
-        }
-        hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> cameraStatuses{};
-        Status status = Status::NO_ERROR;
-        auto remoteRet = mCameraService->addListener_2_1(mCameraServiceListener,
-                                                     [&status, &cameraStatuses](Status s,
-                                                                                auto &retStatuses) {
-                                                         status = s;
-                                                         cameraStatuses = retStatuses;
-                                                     });
-        if (!remoteRet.isOk() || status != Status::NO_ERROR) {
-            ALOGE("Failed to add listener to camera service %s", remoteRet.description().c_str());
-        }
+    std::string serviceName = ICameraService::descriptor;
+    serviceName += "/default";
 
-        // Setup vendor tags
-        if (!setupVendorTags()) {
-            ALOGE("Unable to set up vendor tags");
+    bool isDeclared = AServiceManager_isDeclared(serviceName.c_str());
+    if (!isDeclared) {
+        ALOGE("%s: No ICameraService instance declared: %s", __FUNCTION__, serviceName.c_str());
+        return nullptr;
+    }
+
+    // Before doing any more make sure there is a binder threadpool alive
+    // This is a no-op if the binder threadpool was already started by this process.
+    ABinderProcess_startThreadPool();
+
+    std::shared_ptr<ICameraService> cameraService =
+            ICameraService::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_waitForService(serviceName.c_str())));
+    if (cameraService == nullptr) {
+        ALOGE("%s: Could not get ICameraService instance.", __FUNCTION__);
+        return nullptr;
+    }
+
+    if (mDeathRecipient.get() == nullptr) {
+        mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+                AIBinder_DeathRecipient_new(CameraManagerGlobal::binderDeathCallback));
+    }
+    AIBinder_linkToDeath(cameraService->asBinder().get(),
+                         mDeathRecipient.get(), /*cookie=*/ this);
+
+    mCameraService = cameraService;
+
+    // Setup looper thread to perform availability callbacks
+    if (mCbLooper == nullptr) {
+        mCbLooper = new ALooper;
+        mCbLooper->setName("C2N-mgr-looper");
+        status_t err = mCbLooper->start(
+                /*runOnCallingThread*/false,
+                /*canCallJava*/       true,
+                PRIORITY_DEFAULT);
+        if (err != OK) {
+            ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
+                    __FUNCTION__, strerror(-err), err);
+            mCbLooper.clear();
             return nullptr;
         }
+        if (mHandler == nullptr) {
+            mHandler = new CallbackHandler(weak_from_this());
+        }
+        mCbLooper->registerHandler(mHandler);
+    }
 
-        for (auto& c : cameraStatuses) {
-            onStatusChangedLocked(c.v2_0);
+    // register ICameraServiceListener
+    if (mCameraServiceListener == nullptr) {
+        mCameraServiceListener = ndk::SharedRefBase::make<CameraServiceListener>(weak_from_this());
+    }
 
-            for (auto& unavailablePhysicalId : c.unavailPhysicalCameraIds) {
-                PhysicalCameraStatusAndId statusAndId;
-                statusAndId.deviceStatus = CameraDeviceStatus::STATUS_NOT_PRESENT;
-                statusAndId.cameraId = c.v2_0.cameraId;
-                statusAndId.physicalCameraId = unavailablePhysicalId;
-                onStatusChangedLocked(statusAndId);
-            }
+    std::vector<CameraStatusAndId> cameraStatuses;
+    Status status = Status::NO_ERROR;
+    ScopedAStatus remoteRet = mCameraService->addListener(mCameraServiceListener,
+                                                          &cameraStatuses);
+
+    if (!remoteRet.isOk()) {
+        if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+            ALOGE("%s: Failed to add listener to camera service: %s", __FUNCTION__,
+                toString(errStatus).c_str());
+        } else {
+            ALOGE("%s: Transaction failed when adding listener to camera service: %d",
+                __FUNCTION__, remoteRet.getExceptionCode());
+        }
+    }
+
+    // Setup vendor tags
+    if (!setupVendorTags()) {
+        ALOGE("Unable to set up vendor tags");
+        return nullptr;
+    }
+
+    for (auto& csi: cameraStatuses){
+        onStatusChangedLocked(csi.deviceStatus, csi.cameraId);
+
+        for (auto& unavailablePhysicalId : csi.unavailPhysicalCameraIds) {
+            onStatusChangedLocked(CameraDeviceStatus::STATUS_NOT_PRESENT,
+                                  csi.cameraId, unavailablePhysicalId);
         }
     }
     return mCameraService;
 }
 
-void CameraManagerGlobal::DeathNotifier::serviceDied(uint64_t cookie, const wp<IBase> &who) {
-    (void) cookie;
-    (void) who;
+void CameraManagerGlobal::binderDeathCallback(void* /*cookie*/) {
+    AutoMutex _l(sLock);
+
     ALOGE("Camera service binderDied!");
-    sp<CameraManagerGlobal> cm = mCameraManager.promote();
-    if (cm != nullptr) {
-        AutoMutex lock(cm->mLock);
-        for (auto& pair : cm->mDeviceStatusMap) {
-            CameraStatusAndId cameraStatusAndId;
-            cameraStatusAndId.cameraId = pair.first;
-            cameraStatusAndId.deviceStatus = pair.second.getStatus();
-            cm->onStatusChangedLocked(cameraStatusAndId);
-        }
-        cm->mCameraService.clear();
-        // TODO: consider adding re-connect call here?
+    std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
+    if (instance == nullptr) {
+        return;
     }
+
+    // Remove cameraService from the static instance
+    AutoMutex lock(instance->mLock);
+    for (auto& pair : instance->mDeviceStatusMap) {
+        const auto &cameraId = pair.first;
+        const auto &deviceStatus = pair.second.getStatus();
+        instance->onStatusChangedLocked(deviceStatus, cameraId);
+    }
+    instance->mCameraService.reset();
+    // TODO: consider adding re-connect call here?
 }
 
 void CameraManagerGlobal::registerAvailabilityCallback(
@@ -362,41 +398,45 @@
 void CameraManagerGlobal::registerAvailCallback(const T *callback) {
     Mutex::Autolock _l(mLock);
     Callback cb(callback);
-    auto pair = mCallbacks.insert(cb);
+    auto res = mCallbacks.insert(cb);
+    if (!res.second) {
+        ALOGE("%s: Failed to register callback. Couldn't insert in map.", __FUNCTION__);
+        return;
+    }
     // Send initial callbacks if callback is newly registered
-    if (pair.second) {
-        for (auto& pair : mDeviceStatusMap) {
-            const hidl_string& cameraId = pair.first;
-            CameraDeviceStatus status = pair.second.getStatus();
+    for (auto& pair : mDeviceStatusMap) {
+        const std::string& cameraId = pair.first;
+        CameraDeviceStatus status = pair.second.getStatus();
 
+        {
             // Camera available/unavailable callback
             sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
             ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
-                    cb.mAvailable : cb.mUnavailable;
+                                                         cb.mAvailable : cb.mUnavailable;
             msg->setPointer(kCallbackFpKey, (void *) cbFunc);
             msg->setPointer(kContextKey, cb.mContext);
             msg->setString(kCameraIdKey, AString(cameraId.c_str()));
             mPendingCallbackCnt++;
             msg->post();
+        }
 
-            // Physical camera unavailable callback
-            std::set<hidl_string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
-            for (const auto& physicalCameraId : unavailPhysicalIds) {
-                sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
-                ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
-                        cb.mPhysicalCamUnavailable;
-                msg->setPointer(kCallbackFpKey, (void *) cbFunc);
-                msg->setPointer(kContextKey, cb.mContext);
-                msg->setString(kCameraIdKey, AString(cameraId.c_str()));
-                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
-                mPendingCallbackCnt++;
-                msg->post();
-            }
+        // Physical camera unavailable callback
+        std::set<std::string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
+        for (const auto& physicalCameraId : unavailPhysicalIds) {
+            sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+            ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+                    cb.mPhysicalCamUnavailable;
+            msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+            msg->setPointer(kContextKey, cb.mContext);
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+            mPendingCallbackCnt++;
+            msg->post();
         }
     }
 }
 
-void CameraManagerGlobal::getCameraIdList(std::vector<hidl_string>* cameraIds) {
+void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
     auto cs = getCameraService();
     Mutex::Autolock _l(mLock);
@@ -507,33 +547,31 @@
 }
 
 void CameraManagerGlobal::CallbackHandler::notifyParent() {
-    sp<CameraManagerGlobal> parent = mParent.promote();
+    std::shared_ptr<CameraManagerGlobal> parent = mParent.lock();
     if (parent != nullptr) {
         parent->onCallbackCalled();
     }
 }
 
-hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onStatusChanged(
-        const CameraStatusAndId &statusAndId) {
-    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ScopedAStatus CameraManagerGlobal::CameraServiceListener::onStatusChanged(
+        CameraDeviceStatus status, const std::string &cameraId) {
+    std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
     if (cm != nullptr) {
-        cm->onStatusChanged(statusAndId);
+        cm->onStatusChanged(status, cameraId);
     } else {
         ALOGE("Cannot deliver status change. Global camera manager died");
     }
-    return Void();
+    return ScopedAStatus::ok();
 }
 
 void CameraManagerGlobal::onStatusChanged(
-        const CameraStatusAndId &statusAndId) {
+        const CameraDeviceStatus &status, const std::string &cameraId) {
     Mutex::Autolock _l(mLock);
-    onStatusChangedLocked(statusAndId);
+    onStatusChangedLocked(status, cameraId);
 }
 
 void CameraManagerGlobal::onStatusChangedLocked(
-        const CameraStatusAndId &statusAndId) {
-    hidl_string cameraId = statusAndId.cameraId;
-    CameraDeviceStatus status = statusAndId.deviceStatus;
+        const CameraDeviceStatus &status, const std::string &cameraId) {
     if (!validStatus(status)) {
         ALOGE("%s: Invalid status %d", __FUNCTION__, status);
         return;
@@ -567,28 +605,28 @@
     }
 }
 
-hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
-        const PhysicalCameraStatusAndId &statusAndId) {
-    sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ScopedAStatus CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+        CameraDeviceStatus in_status, const std::string& in_cameraId,
+        const std::string& in_physicalCameraId) {
+    std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
     if (cm != nullptr) {
-        cm->onStatusChanged(statusAndId);
+        cm->onStatusChanged(in_status, in_cameraId, in_physicalCameraId);
     } else {
         ALOGE("Cannot deliver status change. Global camera manager died");
     }
-    return Void();
+    return ScopedAStatus::ok();
 }
 
 void CameraManagerGlobal::onStatusChanged(
-        const PhysicalCameraStatusAndId &statusAndId) {
+        const CameraDeviceStatus &status, const std::string& cameraId,
+        const std::string& physicalCameraId) {
     Mutex::Autolock _l(mLock);
-    onStatusChangedLocked(statusAndId);
+    onStatusChangedLocked(status, cameraId, physicalCameraId);
 }
 
 void CameraManagerGlobal::onStatusChangedLocked(
-        const PhysicalCameraStatusAndId &statusAndId) {
-    hidl_string cameraId = statusAndId.cameraId;
-    hidl_string physicalCameraId = statusAndId.physicalCameraId;
-    CameraDeviceStatus status = statusAndId.deviceStatus;
+        const CameraDeviceStatus &status, const std::string& cameraId,
+        const std::string& physicalCameraId) {
     if (!validStatus(status)) {
         ALOGE("%s: Invalid status %d", __FUNCTION__, status);
         return;
@@ -642,20 +680,20 @@
 }
 
 bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
-        const hidl_string& physicalCameraId) {
+        const std::string& physicalCameraId) {
     std::lock_guard<std::mutex> lock(mLock);
     auto result = unavailablePhysicalIds.insert(physicalCameraId);
     return result.second;
 }
 
 bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
-        const hidl_string& physicalCameraId) {
+        const std::string& physicalCameraId) {
     std::lock_guard<std::mutex> lock(mLock);
     auto count = unavailablePhysicalIds.erase(physicalCameraId);
     return count > 0;
 }
 
-std::set<hidl_string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
+std::set<std::string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
     std::lock_guard<std::mutex> lock(mLock);
     return unavailablePhysicalIds;
 }
@@ -666,16 +704,15 @@
 /**
  * ACameraManger Implementation
  */
-camera_status_t
-ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
+camera_status_t ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
     Mutex::Autolock _l(mLock);
 
-    std::vector<hidl_string> idList;
-    CameraManagerGlobal::getInstance().getCameraIdList(&idList);
+    std::vector<std::string> idList;
+    CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
 
     int numCameras = idList.size();
     ACameraIdList *out = new ACameraIdList;
-    if (!out) {
+    if (out == nullptr) {
         ALOGE("Allocate memory for ACameraIdList failed!");
         return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
     }
@@ -717,33 +754,37 @@
     }
 }
 
-camera_status_t ACameraManager::getCameraCharacteristics(
-        const char *cameraIdStr, sp<ACameraMetadata> *characteristics) {
+camera_status_t ACameraManager::getCameraCharacteristics(const char *cameraIdStr,
+                                                         sp<ACameraMetadata> *characteristics) {
+    using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
     Mutex::Autolock _l(mLock);
 
-    sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
     if (cs == nullptr) {
         ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
-    CameraMetadata rawMetadata;
-    Status status = Status::NO_ERROR;
-    auto serviceRet =
-        cs->getCameraCharacteristics(cameraIdStr,
-                                     [&status, &rawMetadata] (auto s ,
-                                                              const hidl_vec<uint8_t> &metadata) {
-                                          status = s;
-                                          if (status == Status::NO_ERROR) {
-                                              utils::convertFromHidlCloned(metadata, &rawMetadata);
-                                          }
-                                     });
-    if (!serviceRet.isOk() || status != Status::NO_ERROR) {
-        ALOGE("Get camera characteristics from camera service failed");
+    AidlCameraMetadata rawMetadata;
+    ScopedAStatus serviceRet = cs->getCameraCharacteristics(cameraIdStr, &rawMetadata);
+
+    if (!serviceRet.isOk()) {
+        if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
+            ALOGE("%s: Get camera characteristics from camera service failed: %s",
+                __FUNCTION__, toString(errStatus).c_str());
+        } else {
+            ALOGE("%s: Transaction error when getting camera "
+                  "characteristics from camera service: %d",
+                __FUNCTION__, serviceRet.getExceptionCode());
+        }
         return ACAMERA_ERROR_UNKNOWN; // should not reach here
     }
 
-    *characteristics = new ACameraMetadata(
-            rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
+    camera_metadata_t* metadataBuffer;
+    ::android::acam::utils::cloneFromAidl(rawMetadata, &metadataBuffer);
+
+    *characteristics = new ACameraMetadata(metadataBuffer,
+                                           ACameraMetadata::ACM_CHARACTERISTICS);
     return ACAMERA_OK;
 }
 
@@ -763,42 +804,41 @@
 
     ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars));
 
-    sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+    std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
     if (cs == nullptr) {
         ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
         delete device;
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
 
-    sp<ICameraDeviceCallback> callbacks = device->getServiceCallback();
-    sp<ICameraDeviceUser_2_0> deviceRemote_2_0;
+    std::shared_ptr<BnCameraDeviceCallback> deviceCallback = device->getServiceCallback();
+    std::shared_ptr<ICameraDeviceUser> deviceRemote;
 
     // No way to get package name from native.
     // Send a zero length package name and let camera service figure it out from UID
-    Status status = Status::NO_ERROR;
-    auto serviceRet = cs->connectDevice(
-            callbacks, cameraId, [&status, &deviceRemote_2_0](auto s, auto &device) {
-                                     status = s;
-                                     deviceRemote_2_0 = device;
-                                 });
-
-    if (!serviceRet.isOk() || status != Status::NO_ERROR) {
-        ALOGE("%s: connect camera device failed", __FUNCTION__);
-        delete device;
-        return utils::convertFromHidl(status);
+    ScopedAStatus serviceRet = cs->connectDevice(deviceCallback,
+                                                 std::string(cameraId), &deviceRemote);
+    if (!serviceRet.isOk()) {
+        if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+            Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
+            ALOGE("%s: connect camera device failed: %s",
+                  __FUNCTION__, toString(errStatus).c_str());
+            delete device;
+            return utils::convertFromAidl(errStatus);
+        } else {
+            ALOGE("%s: Transaction failed when connecting camera device: %d",
+                __FUNCTION__, serviceRet.getExceptionCode());
+            delete device;
+            return ACAMERA_ERROR_UNKNOWN;
+        }
     }
-    if (deviceRemote_2_0 == nullptr) {
+
+    if (deviceRemote == nullptr) {
         ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
         delete device;
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
-    auto castResult = ICameraDeviceUser::castFrom(deviceRemote_2_0);
-    if (!castResult.isOk()) {
-        ALOGE("%s: failed to cast remote device to version 2.1", __FUNCTION__);
-        delete device;
-        return ACAMERA_ERROR_CAMERA_DISCONNECTED;
-    }
-    sp<ICameraDeviceUser> deviceRemote = castResult;
+
     device->setRemoteDevice(deviceRemote);
     device->setDeviceMetadataQueues();
     *outDevice = device;
@@ -821,7 +861,7 @@
     sp<VendorTagDescriptorCache> vtCache = VendorTagDescriptorCache::getGlobalVendorTagCache();
     sp<VendorTagDescriptor> vTags = nullptr;
     vtCache->getVendorTagDescriptor(vendorTagId, &vTags);
-    status_t status= metadata.getTagFromName(name, vTags.get(), tag);
+    status_t status = CameraMetadata::getTagFromName(name, vTags.get(), tag);
     return status == OK ? ACAMERA_OK : ACAMERA_ERROR_METADATA_NOT_FOUND;
 }
 
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 4663529..85acee7 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -17,39 +17,35 @@
 #ifndef _ACAMERA_MANAGER_H
 #define _ACAMERA_MANAGER_H
 
-#include <camera/NdkCameraManager.h>
-
-#include <android-base/parseint.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.2/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
-
 #include <CameraMetadata.h>
-#include <utils/StrongPointer.h>
-#include <utils/Mutex.h>
-
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <set>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/common/VendorTag.h>
+#include <aidl/android/frameworks/cameraservice/common/VendorTagSection.h>
+#include <aidl/android/frameworks/cameraservice/service/BnCameraServiceListener.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraService.h>
+#include <android-base/parseint.h>
+#include <camera/NdkCameraManager.h>
 #include <map>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <set>
+#include <utility>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
 
 namespace android {
 namespace acam {
 
-using ICameraService = frameworks::cameraservice::service::V2_2::ICameraService;
-using CameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus;
-using ICameraServiceListener = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
-using PhysicalCameraStatusAndId = frameworks::cameraservice::service::V2_1::PhysicalCameraStatusAndId;
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using VendorTagSection = frameworks::cameraservice::common::V2_0::VendorTagSection;
-using VendorTag = frameworks::cameraservice::common::V2_0::VendorTag;
-using IBase = android::hidl::base::V1_0::IBase;
-using android::hardware::hidl_string;
-using hardware::Void;
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::common::VendorTag;
+using ::aidl::android::frameworks::cameraservice::common::VendorTagSection;
+using ::aidl::android::frameworks::cameraservice::service::BnCameraServiceListener;
+using ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using ::aidl::android::frameworks::cameraservice::service::ICameraService;
 
 /**
  * Per-process singleton instance of CameraManger. Shared by all ACameraManager
@@ -58,15 +54,18 @@
  *
  * TODO: maybe CameraManagerGlobal is better suited in libcameraclient?
  */
-class CameraManagerGlobal final : public RefBase {
+class CameraManagerGlobal final: public std::enable_shared_from_this<CameraManagerGlobal> {
   public:
-    static CameraManagerGlobal& getInstance();
-    sp<ICameraService> getCameraService();
+    static std::shared_ptr<CameraManagerGlobal> getInstance();
+    static void binderDeathCallback(void* cookie);
 
-    void registerAvailabilityCallback(
-            const ACameraManager_AvailabilityCallbacks *callback);
-    void unregisterAvailabilityCallback(
-            const ACameraManager_AvailabilityCallbacks *callback);
+    CameraManagerGlobal() {};
+    ~CameraManagerGlobal();
+
+    std::shared_ptr<ICameraService> getCameraService();
+
+    void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks *callback);
+    void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks *callback);
 
     void registerExtendedAvailabilityCallback(
             const ACameraManager_ExtendedAvailabilityCallbacks* callback);
@@ -76,35 +75,28 @@
     /**
      * Return camera IDs that support camera2
      */
-    void getCameraIdList(std::vector<hidl_string> *cameraIds);
+    void getCameraIdList(std::vector<std::string> *cameraIds);
 
   private:
-    sp<ICameraService> mCameraService;
+    std::shared_ptr<ICameraService> mCameraService;
     const int          kCameraServicePollDelay = 500000; // 0.5s
     Mutex              mLock;
-    class DeathNotifier : public android::hardware::hidl_death_recipient {
-      public:
-        explicit DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
-      protected:
-        // IBinder::DeathRecipient implementation
-        virtual void serviceDied(uint64_t cookie, const wp<IBase> &who);
-      private:
-        const wp<CameraManagerGlobal> mCameraManager;
-    };
-    sp<DeathNotifier> mDeathNotifier;
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
 
-    class CameraServiceListener final : public ICameraServiceListener {
+    class CameraServiceListener final : public BnCameraServiceListener {
       public:
-        explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
-        android::hardware::Return<void> onStatusChanged(
-            const CameraStatusAndId &statusAndId) override;
-        android::hardware::Return<void> onPhysicalCameraStatusChanged(
-            const PhysicalCameraStatusAndId &statusAndId) override;
+        explicit CameraServiceListener(std::weak_ptr<CameraManagerGlobal> cm) :
+              mCameraManager(std::move(cm)) {}
+        ndk::ScopedAStatus onPhysicalCameraStatusChanged(
+                CameraDeviceStatus in_status, const std::string& in_cameraId,
+                const std::string& in_physicalCameraId) override;
+        ndk::ScopedAStatus onStatusChanged(CameraDeviceStatus in_status,
+                                           const std::string& in_cameraId) override;
 
       private:
-        const wp<CameraManagerGlobal> mCameraManager;
+        const std::weak_ptr<CameraManagerGlobal> mCameraManager;
     };
-    sp<CameraServiceListener> mCameraServiceListener;
+    std::shared_ptr<CameraServiceListener> mCameraServiceListener;
 
     // Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
     struct Callback {
@@ -180,20 +172,22 @@
     static const nsecs_t kCallbackDrainTimeout;
     class CallbackHandler : public AHandler {
       public:
-        CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
+        CallbackHandler(std::weak_ptr<CameraManagerGlobal> parent) : mParent(std::move(parent)) {}
         void onMessageReceived(const sp<AMessage> &msg) override;
       private:
-        wp<CameraManagerGlobal> mParent;
+        std::weak_ptr<CameraManagerGlobal> mParent;
         void notifyParent();
         void onMessageReceivedInternal(const sp<AMessage> &msg);
     };
     sp<CallbackHandler> mHandler;
     sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
 
-    void onStatusChanged(const CameraStatusAndId &statusAndId);
-    void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
-    void onStatusChanged(const PhysicalCameraStatusAndId &statusAndId);
-    void onStatusChangedLocked(const PhysicalCameraStatusAndId &statusAndId);
+    void onStatusChanged(const CameraDeviceStatus &status, const std::string &cameraId);
+    void onStatusChangedLocked(const CameraDeviceStatus &status, const std::string &cameraId);
+    void onStatusChanged(const CameraDeviceStatus &status, const std::string &cameraId,
+                         const std::string &physicalCameraId);
+    void onStatusChangedLocked(const CameraDeviceStatus &status, const std::string &cameraId,
+                               const std::string &physicalCameraId);
     bool setupVendorTags();
 
     // Utils for status
@@ -203,7 +197,7 @@
     // The sort logic must match the logic in
     // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
     struct CameraIdComparator {
-        bool operator()(const hidl_string& a, const hidl_string& b) const {
+        bool operator()(const std::string& a, const std::string& b) const {
             uint32_t aUint = 0, bUint = 0;
             bool aIsUint = base::ParseUint(a.c_str(), &aUint);
             bool bIsUint = base::ParseUint(b.c_str(), &bUint);
@@ -225,29 +219,29 @@
       private:
         CameraDeviceStatus status = CameraDeviceStatus::STATUS_NOT_PRESENT;
         mutable std::mutex mLock;
-        std::set<hidl_string> unavailablePhysicalIds;
+        std::set<std::string> unavailablePhysicalIds;
       public:
         CameraStatus(CameraDeviceStatus st): status(st) { };
         CameraStatus() = default;
 
-        bool addUnavailablePhysicalId(const hidl_string& physicalCameraId);
-        bool removeUnavailablePhysicalId(const hidl_string& physicalCameraId);
+        bool addUnavailablePhysicalId(const std::string& physicalCameraId);
+        bool removeUnavailablePhysicalId(const std::string& physicalCameraId);
         CameraDeviceStatus getStatus();
         void updateStatus(CameraDeviceStatus newStatus);
-        std::set<hidl_string> getUnavailablePhysicalIds();
+        std::set<std::string> getUnavailablePhysicalIds();
     };
 
     template <class T>
     void registerAvailCallback(const T *callback);
 
     // Map camera_id -> status
-    std::map<hidl_string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
+    std::map<std::string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
-    static CameraManagerGlobal* sInstance;
-    CameraManagerGlobal() {};
-    ~CameraManagerGlobal();
+    // Static instance is stored in a weak pointer, so will only exist if there is at least one
+    // active consumer of CameraManagerGlobal
+    static std::weak_ptr<CameraManagerGlobal> sInstance;
 };
 
 } // namespace acam;
@@ -259,7 +253,7 @@
  */
 struct ACameraManager {
     ACameraManager() :
-            mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {}
+            mGlobalManager(android::acam::CameraManagerGlobal::getInstance()) {}
     ~ACameraManager();
     camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
     static void     deleteCameraIdList(ACameraIdList* cameraIdList);
@@ -277,7 +271,7 @@
         kCameraIdListNotInit = -1
     };
     android::Mutex         mLock;
-    android::sp<android::acam::CameraManagerGlobal> mGlobalManager;
+    std::shared_ptr<android::acam::CameraManagerGlobal> mGlobalManager;
 };
 
 #endif //_ACAMERA_MANAGER_H
diff --git a/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h b/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
index 5715d77..fcb7e34 100644
--- a/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
@@ -16,6 +16,7 @@
 
 #include "utils.h"
 
+using ::android::acam::utils::native_handle_ptr_wrapper;
 struct ACameraOutputTarget {
     explicit ACameraOutputTarget(const native_handle_t* window) : mWindow(window) {};
 
@@ -32,5 +33,5 @@
         return mWindow > other.mWindow;
     }
 
-    android::acam::utils::native_handle_ptr_wrapper mWindow;
+    native_handle_ptr_wrapper mWindow;
 };
diff --git a/camera/ndk/ndk_vendor/impl/utils.cpp b/camera/ndk/ndk_vendor/impl/utils.cpp
index e4fb204..73a527b 100644
--- a/camera/ndk/ndk_vendor/impl/utils.cpp
+++ b/camera/ndk/ndk_vendor/impl/utils.cpp
@@ -16,66 +16,75 @@
 
 #define LOG_TAG "ACameraVendorUtils"
 
-#include <utils/Log.h>
-
 #include "utils.h"
 
+#include <aidlcommonsupport/NativeHandle.h>
+#include <utils/Log.h>
+
 namespace android {
 namespace acam {
 namespace utils {
 
-// Convert CaptureRequest wrappable by sp<> to hidl CaptureRequest.
-frameworks::cameraservice::device::V2_0::CaptureRequest
-convertToHidl(const CaptureRequest *captureRequest) {
-    frameworks::cameraservice::device::V2_0::CaptureRequest hCaptureRequest;
-    hCaptureRequest.physicalCameraSettings = captureRequest->mCaptureRequest.physicalCameraSettings;
-    hCaptureRequest.streamAndWindowIds = captureRequest->mCaptureRequest.streamAndWindowIds;
-    return hCaptureRequest;
+// Convert CaptureRequest wrappable by sp<> to aidl CaptureRequest.
+AidlCaptureRequest convertToAidl(const CaptureRequest *captureRequest) {
+    AidlCaptureRequest aidlCaptureRequest;
+    aidlCaptureRequest.physicalCameraSettings =
+            captureRequest->mCaptureRequest.physicalCameraSettings;
+    aidlCaptureRequest.streamAndWindowIds = captureRequest->mCaptureRequest.streamAndWindowIds;
+    return aidlCaptureRequest;
 }
 
-HRotation convertToHidl(int rotation) {
-    HRotation hRotation = HRotation::R0;
+OutputConfiguration::Rotation convertToAidl(int rotation) {
+    using AidlRotation = OutputConfiguration::Rotation;
+
+    AidlRotation aRot = AidlRotation ::R0;
     switch(rotation) {
         case CAMERA3_STREAM_ROTATION_90:
-            hRotation = HRotation::R90;
+            aRot = AidlRotation::R90;
             break;
         case CAMERA3_STREAM_ROTATION_180:
-            hRotation = HRotation::R180;
+            aRot = AidlRotation::R180;
             break;
         case CAMERA3_STREAM_ROTATION_270:
-            hRotation = HRotation::R270;
+            aRot = AidlRotation::R270;
             break;
         default:
             break;
     }
-    return hRotation;
+    return aRot;
 }
 
-bool convertFromHidlCloned(const HCameraMetadata &metadata, CameraMetadata *rawMetadata) {
-    const camera_metadata *buffer = (camera_metadata_t*)(metadata.data());
-    size_t expectedSize = metadata.size();
+bool cloneFromAidl(const AidlCameraMetadata& srcMetadata, camera_metadata_t** dst) {
+    const camera_metadata *buffer = (camera_metadata_t*)(srcMetadata.metadata.data());
+    size_t expectedSize = srcMetadata.metadata.size();
     int ret = validate_camera_metadata_structure(buffer, &expectedSize);
-    if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
-        *rawMetadata = buffer;
-    } else {
-        ALOGE("%s: Malformed camera metadata received from caller", __FUNCTION__);
+    if (ret != OK && ret != CAMERA_METADATA_VALIDATION_SHIFTED) {
+        ALOGE("%s: Malformed camera srcMetadata received from caller", __FUNCTION__);
         return false;
     }
-    return true;
+
+    camera_metadata_t* clonedBuffer = clone_camera_metadata(buffer);
+    if (clonedBuffer != nullptr) {
+        *dst = clonedBuffer;
+        return true;
+    }
+
+    ALOGE("%s: Failed to clone srcMetadata buffer.", __FUNCTION__);
+    return false;
 }
 
-// Note: existing data in dst will be gone. dst owns memory if shouldOwn is set
-//       to true.
-void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst, bool shouldOwn) {
+// Note: existing data in dst will be gone.
+void convertToAidl(const camera_metadata_t *src, AidlCameraMetadata* dst) {
     if (src == nullptr) {
         return;
     }
     size_t size = get_camera_metadata_size(src);
-    dst->setToExternal((uint8_t *) src, size, shouldOwn);
-    return;
+    uint8_t* metadataStart = (uint8_t*)src;
+    uint8_t* metadataEnd = metadataStart + size;
+    dst->metadata.assign(metadataStart, metadataEnd);
 }
 
-TemplateId convertToHidl(ACameraDevice_request_template templateId) {
+TemplateId convertToAidl(ACameraDevice_request_template templateId) {
     switch(templateId) {
         case TEMPLATE_STILL_CAPTURE:
             return TemplateId::STILL_CAPTURE;
@@ -92,7 +101,7 @@
     }
 }
 
-camera_status_t convertFromHidl(Status status) {
+camera_status_t convertFromAidl(Status status) {
     camera_status_t ret = ACAMERA_OK;
     switch(status) {
         case Status::NO_ERROR:
@@ -146,6 +155,14 @@
     return true;
 }
 
+bool isWindowNativeHandleEqual(const native_handle_t *nh1,
+                               const aidl::android::hardware::common::NativeHandle& nh2) {
+    native_handle_t* tempNh = makeFromAidl(nh2);
+    bool equal = isWindowNativeHandleEqual(nh1, tempNh);
+    native_handle_delete(tempNh);
+    return equal;
+}
+
 bool isWindowNativeHandleLessThan(const native_handle_t *nh1, const native_handle_t *nh2) {
     if (isWindowNativeHandleEqual(nh1, nh2)) {
         return false;
@@ -166,32 +183,6 @@
     return !isWindowNativeHandleLessThan(nh1, nh2) && !isWindowNativeHandleEqual(nh1, nh2);
 }
 
-bool areWindowNativeHandlesEqual(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle> handles2) {
-    if (handles1.size() != handles2.size()) {
-        return false;
-    }
-    for (int i = 0; i < handles1.size(); i++) {
-        if (!isWindowNativeHandleEqual(handles1[i], handles2[i])) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool areWindowNativeHandlesLessThan(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2) {
-    if (handles1.size() != handles2.size()) {
-        return handles1.size() < handles2.size();
-    }
-    for (int i = 0; i < handles1.size(); i++) {
-        const native_handle_t *handle1 = handles1[i].getNativeHandle();
-        const native_handle_t *handle2 = handles2[i].getNativeHandle();
-        if (!isWindowNativeHandleEqual(handle1, handle2)) {
-            return isWindowNativeHandleLessThan(handle1, handle2);
-        }
-    }
-    return false;
-}
-
 } // namespace utils
 } // namespace acam
 } // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/utils.h b/camera/ndk/ndk_vendor/impl/utils.h
index 62779a4..7ad74ad 100644
--- a/camera/ndk/ndk_vendor/impl/utils.h
+++ b/camera/ndk/ndk_vendor/impl/utils.h
@@ -14,46 +14,39 @@
  * limitations under the License.
  */
 
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <camera/NdkCameraDevice.h>
+#ifndef CAMERA_NDK_VENDOR_UTILS_H
+#define CAMERA_NDK_VENDOR_UTILS_H
+
 #include <CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureRequest.h>
+#include <aidl/android/frameworks/cameraservice/device/ICameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraService.h>
+#include <camera/NdkCameraDevice.h>
 #include <hardware/camera3.h>
-
-#ifndef CAMERA_NDK_VENDOR_H
-#define CAMERA_NDK_VENDOR_H
-
-using android::hardware::hidl_vec;
-using android::hardware::hidl_handle;
+#include <utils/RefBase.h>
 
 namespace android {
 namespace acam {
 namespace utils {
 
-using CameraMetadata = hardware::camera::common::V1_0::helper::CameraMetadata;
-using HCameraMetadata  = frameworks::cameraservice::service::V2_0::CameraMetadata;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using TemplateId = frameworks::cameraservice::device::V2_0::TemplateId;
-using PhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
-using HRotation = frameworks::cameraservice::device::V2_0::OutputConfiguration::Rotation;
-using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
-
-// Utility class so that CaptureRequest can be stored by sp<>
-struct CaptureRequest : public RefBase {
-  frameworks::cameraservice::device::V2_0::CaptureRequest mCaptureRequest;
-  std::vector<const native_handle_t *> mSurfaceList;
-  //Physical camera settings metadata is stored here, since the capture request
-  //might not contain it. That's since, fmq might have consumed it.
-  hidl_vec<PhysicalCameraSettings> mPhysicalCameraSettings;
-};
-
-bool areWindowNativeHandlesEqual(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2);
-
-bool areWindowNativeHandlesLessThan(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2);
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using ::aidl::android::frameworks::cameraservice::device::TemplateId;
+using ::aidl::android::hardware::common::NativeHandle;
+using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
+using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using AidlCaptureRequest = ::aidl::android::frameworks::cameraservice::device::CaptureRequest;
 
 bool isWindowNativeHandleEqual(const native_handle_t *nh1, const native_handle_t *nh2);
 
+bool isWindowNativeHandleEqual(const native_handle_t* nh1, const NativeHandle& nh2);
+
 bool isWindowNativeHandleLessThan(const native_handle_t *nh1, const native_handle_t *nh2);
 
 // Convenience wrapper over isWindowNativeHandleLessThan and isWindowNativeHandleEqual
@@ -88,117 +81,30 @@
 
 };
 
-// Wrapper around OutputConfiguration. This is needed since HIDL
-// OutputConfiguration is auto-generated and marked final. Therefore, operator
-// overloads outside the class, will not get picked by clang while trying to
-// store OutputConfiguration in maps/sets.
-struct OutputConfigurationWrapper {
-    OutputConfiguration mOutputConfiguration;
-
-    operator const OutputConfiguration &() const {
-        return mOutputConfiguration;
-    }
-
-    OutputConfigurationWrapper() {
-        mOutputConfiguration.rotation = OutputConfiguration::Rotation::R0;
-        // The ndk currently doesn't support deferred surfaces
-        mOutputConfiguration.isDeferred = false;
-        mOutputConfiguration.width = 0;
-        mOutputConfiguration.height = 0;
-        // ndk doesn't support inter OutputConfiguration buffer sharing.
-        mOutputConfiguration.windowGroupId = -1;
-    };
-
-    OutputConfigurationWrapper(const OutputConfigurationWrapper &other) {
-        *this = other;
-    }
-
-    // Needed to make sure that OutputConfiguration in
-    // OutputConfigurationWrapper, when copied doesn't call hidl_handle's
-    // assignment operator / copy constructor, which will lead to native handle
-    // cloning, which is not what we want for app callbacks which have the native
-    // handle as parameter.
-    OutputConfigurationWrapper &operator=(const OutputConfigurationWrapper &other) {
-        const OutputConfiguration &outputConfiguration = other.mOutputConfiguration;
-        mOutputConfiguration.rotation = outputConfiguration.rotation;
-        mOutputConfiguration.isDeferred = outputConfiguration.isDeferred;
-        mOutputConfiguration.width = outputConfiguration.width;
-        mOutputConfiguration.height = outputConfiguration.height;
-        mOutputConfiguration.windowGroupId = outputConfiguration.windowGroupId;
-        mOutputConfiguration.windowHandles.resize(outputConfiguration.windowHandles.size());
-        mOutputConfiguration.physicalCameraId = outputConfiguration.physicalCameraId;
-        size_t i = 0;
-        for (const auto &handle : outputConfiguration.windowHandles) {
-            mOutputConfiguration.windowHandles[i++] = handle.getNativeHandle();
-        }
-        return *this;
-    }
-
-    bool operator ==(const OutputConfiguration &other) const {
-        const OutputConfiguration &self = mOutputConfiguration;
-        return self.rotation == other.rotation && self.windowGroupId == other.windowGroupId &&
-                self.physicalCameraId == other.physicalCameraId && self.width == other.width &&
-                self.height == other.height && self.isDeferred == other.isDeferred &&
-                areWindowNativeHandlesEqual(self.windowHandles, other.windowHandles);
-    }
-
-    bool operator < (const OutputConfiguration &other) const {
-        if (*this == other) {
-            return false;
-        }
-        const OutputConfiguration &self = mOutputConfiguration;
-        if (self.windowGroupId != other.windowGroupId) {
-            return self.windowGroupId < other.windowGroupId;
-        }
-
-        if (self.width != other.width) {
-            return self.width < other.width;
-        }
-
-        if (self.height != other.height) {
-            return self.height < other.height;
-        }
-
-        if (self.rotation != other.rotation) {
-            return static_cast<uint32_t>(self.rotation) < static_cast<uint32_t>(other.rotation);
-        }
-
-        if (self.isDeferred != other.isDeferred) {
-            return self.isDeferred < other.isDeferred;
-        }
-
-        if (self.physicalCameraId != other.physicalCameraId) {
-            return self.physicalCameraId < other.physicalCameraId;
-        }
-        return areWindowNativeHandlesLessThan(self.windowHandles, other.windowHandles);
-    }
-
-    bool operator != (const OutputConfiguration &other) const {
-        return !(*this == other);
-    }
-
-    bool operator > (const OutputConfiguration &other) const {
-        return (*this != other) && !(*this < other);
-    }
+// Utility class so that CaptureRequest can be stored by sp<>
+struct CaptureRequest: public RefBase {
+  AidlCaptureRequest mCaptureRequest;
+  std::vector<native_handle_ptr_wrapper> mSurfaceList;
+  // Physical camera settings metadata is stored here, as the capture request
+  // might not contain it. That's since, fmq might have consumed it.
+  std::vector<PhysicalCameraSettings> mPhysicalCameraSettings;
 };
 
-// Convert CaptureRequest wrappable by sp<> to hidl CaptureRequest.
-frameworks::cameraservice::device::V2_0::CaptureRequest convertToHidl(
-    const CaptureRequest *captureRequest);
+AidlCaptureRequest convertToAidl(const CaptureRequest *captureRequest);
 
-HRotation convertToHidl(int rotation);
+OutputConfiguration::Rotation convertToAidl(int rotation);
 
-bool convertFromHidlCloned(const HCameraMetadata &metadata, CameraMetadata *rawMetadata);
+bool cloneFromAidl(const AidlCameraMetadata & srcMetadata, camera_metadata_t** dst);
 
 // Note: existing data in dst will be gone.
-void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst, bool shouldOwn = false);
+void convertToAidl(const camera_metadata_t *src, AidlCameraMetadata * dst);
 
-TemplateId convertToHidl(ACameraDevice_request_template templateId);
+TemplateId convertToAidl(ACameraDevice_request_template templateId);
 
-camera_status_t convertFromHidl(Status status);
+camera_status_t convertFromAidl(Status status);
 
 } // namespace utils
 } // namespace acam
 } // namespace android
 
-#endif // CAMERA_NDK_VENDOR_H
+#endif // CAMERA_NDK_VENDOR_UTILS_H
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 63cdb76..3a13a73 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -254,20 +254,22 @@
                 &mLogicalCaptureCallbacksV2, 1, &mStillRequest, &seqId);
     }
 
-    bool checkCallbacks(int pictureCount) {
+    bool checkCallbacks(int pictureCount, bool printLog = false) {
         std::lock_guard<std::mutex> lock(mMutex);
         if (mCompletedCaptureCallbackCount != pictureCount) {
-            ALOGE("Completed capture callback count not as expected. expected %d actual %d",
-                  pictureCount, mCompletedCaptureCallbackCount);
+            ALOGE_IF(printLog,
+                     "Completed capture callback count not as expected. expected %d actual %d",
+                     pictureCount, mCompletedCaptureCallbackCount);
             return false;
         }
         return true;
     }
-    bool checkCallbacksV2(int pictureCount) {
+    bool checkCallbacksV2(int pictureCount, bool printLog = false) {
         std::lock_guard<std::mutex> lock(mMutex);
         if (mCaptureStartedCallbackCount != pictureCount) {
-            ALOGE("Capture started callback count not as expected. expected %d actual %d",
-                  pictureCount, mCaptureStartedCallbackCount);
+            ALOGE_IF(printLog,
+                     "Capture started callback count not as expected. expected %d actual %d",
+                     pictureCount, mCaptureStartedCallbackCount);
             return false;
         }
         return true;
@@ -670,15 +672,22 @@
         // Sleep until all capture finished
         for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
             usleep(kCaptureWaitUs);
-            if (testCase.getAcquiredImageCount() == pictureCount) {
+            bool receivedAllCallbacks = v2 ? cameraHelper.checkCallbacksV2(pictureCount)
+                                           : cameraHelper.checkCallbacks(pictureCount);
+
+            bool acquiredAllImages = testCase.getAcquiredImageCount() == pictureCount;
+            if (acquiredAllImages) {
                 ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
                       pictureCount);
+            }
+            // Wait for all images to be acquired and all callbacks to be processed
+            if (acquiredAllImages && receivedAllCallbacks) {
                 break;
             }
         }
         return testCase.getAcquiredImageCount() == pictureCount &&
-               v2 ? cameraHelper.checkCallbacksV2(pictureCount) :
-                    cameraHelper.checkCallbacks(pictureCount);
+               v2 ? cameraHelper.checkCallbacksV2(pictureCount, /* printLog= */true) :
+                    cameraHelper.checkCallbacks(pictureCount, /* printLog= */true);
     }
 
     bool testTakePicturesNative(const char* id) {
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index ea1ec0c..42e4717 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -53,6 +53,7 @@
 using media::audio::common::AudioDeviceAddress;
 using media::audio::common::AudioDeviceDescription;
 using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
 using media::audio::common::AudioEncapsulationMetadataType;
 using media::audio::common::AudioEncapsulationMode;
 using media::audio::common::AudioEncapsulationType;
@@ -63,9 +64,11 @@
 using media::audio::common::AudioGainMode;
 using media::audio::common::AudioInputFlags;
 using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
 using media::audio::common::AudioMode;
 using media::audio::common::AudioOffloadInfo;
 using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
 using media::audio::common::AudioPortDeviceExt;
 using media::audio::common::AudioPortExt;
 using media::audio::common::AudioPortMixExt;
@@ -2046,6 +2049,10 @@
             return AUDIO_STANDARD_NONE;
         case AudioStandard::EDID:
             return AUDIO_STANDARD_EDID;
+        case AudioStandard::SADB:
+            return AUDIO_STANDARD_SADB;
+        case AudioStandard::VSADB:
+            return AUDIO_STANDARD_VSADB;
     }
     return unexpected(BAD_VALUE);
 }
@@ -2057,6 +2064,10 @@
             return AudioStandard::NONE;
         case AUDIO_STANDARD_EDID:
             return AudioStandard::EDID;
+        case AUDIO_STANDARD_SADB:
+            return AudioStandard::SADB;
+        case AUDIO_STANDARD_VSADB:
+            return AudioStandard::VSADB;
     }
     return unexpected(BAD_VALUE);
 }
@@ -2123,6 +2134,139 @@
     return unexpected(BAD_VALUE);
 }
 
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+    switch (aidl) {
+        case AudioDualMonoMode::OFF:
+            return AUDIO_DUAL_MONO_MODE_OFF;
+        case AudioDualMonoMode::LR:
+            return AUDIO_DUAL_MONO_MODE_LR;
+        case AudioDualMonoMode::LL:
+            return AUDIO_DUAL_MONO_MODE_LL;
+        case AudioDualMonoMode::RR:
+            return AUDIO_DUAL_MONO_MODE_RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_DUAL_MONO_MODE_OFF:
+            return AudioDualMonoMode::OFF;
+        case AUDIO_DUAL_MONO_MODE_LR:
+            return AudioDualMonoMode::LR;
+        case AUDIO_DUAL_MONO_MODE_LL:
+            return AudioDualMonoMode::LL;
+        case AUDIO_DUAL_MONO_MODE_RR:
+            return AudioDualMonoMode::RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        AudioPlaybackRate::TimestretchFallbackMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+            return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+            return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+        case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+            return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+        case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+            return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+        case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+        case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+            return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+        case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+            return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        AudioPlaybackRate::TimestretchMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchMode::DEFAULT:
+            return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+        case AudioPlaybackRate::TimestretchMode::VOICE:
+            return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+            return AudioPlaybackRate::TimestretchMode::DEFAULT;
+        case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+            return AudioPlaybackRate::TimestretchMode::VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+    audio_playback_rate_t legacy;
+    legacy.mSpeed = aidl.speed;
+    legacy.mPitch = aidl.pitch;
+    legacy.mFallbackMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+                    aidl.fallbackMode));
+    legacy.mStretchMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+    return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+    AudioPlaybackRate aidl;
+    aidl.speed = legacy.mSpeed;
+    aidl.pitch = legacy.mPitch;
+    aidl.fallbackMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+                    legacy.mFallbackMode));
+    aidl.timestretchMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+    return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+    switch (aidl) {
+        case AudioLatencyMode::FREE:
+            return AUDIO_LATENCY_MODE_FREE;
+        case AudioLatencyMode::LOW:
+            return AUDIO_LATENCY_MODE_LOW;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_LATENCY_MODE_FREE:
+            return AudioLatencyMode::FREE;
+        case AUDIO_LATENCY_MODE_LOW:
+            return AudioLatencyMode::LOW;
+    }
+    return unexpected(BAD_VALUE);
+}
+
 }  // namespace android
 
 #if defined(BACKEND_NDK)
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index e1efff9..c25ddb1 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -35,6 +35,7 @@
 #include PREFIX(android/media/audio/common/AudioConfigBase.h)
 #include PREFIX(android/media/audio/common/AudioContentType.h)
 #include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
 #include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
 #include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
 #include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
@@ -44,11 +45,13 @@
 #include PREFIX(android/media/audio/common/AudioGainMode.h)
 #include PREFIX(android/media/audio/common/AudioInputFlags.h)
 #include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
 #include PREFIX(android/media/audio/common/AudioMode.h)
 #include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
 #include PREFIX(android/media/audio/common/AudioOutputFlags.h)
 #include PREFIX(android/media/audio/common/AudioPortExt.h)
 #include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
 #include PREFIX(android/media/audio/common/AudioProfile.h)
 #include PREFIX(android/media/audio/common/AudioSource.h)
 #include PREFIX(android/media/audio/common/AudioStandard.h)
@@ -287,8 +290,38 @@
 ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
         const audio_uuid_t& legacy);
 
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+        const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
 }  // namespace android
 
 #if defined(BACKEND_NDK)
 } // aidl
-#endif
\ No newline at end of file
+#endif
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 1d8aea3..ba25226 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -80,6 +80,7 @@
         "libbase",
         "libdmabufheap",
         "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.bufferpool2-V1-ndk",
     ],
 
     local_include_dirs: [
@@ -94,8 +95,12 @@
     shared_libs: [
         "android.hardware.graphics.bufferqueue@2.0",
         "android.hardware.graphics.common@1.2",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
         "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.bufferpool2-V1-ndk",
         "libbase",
+        "libbinder_ndk",
         "libcutils",
         "libdl",
         "libdmabufheap",
@@ -107,6 +112,7 @@
         "libnativewindow",
         "libstagefright_foundation",
         "libstagefright_bufferpool@2.0.1",
+        "libstagefright_aidl_bufferpool2",
         "libui",
         "libutils",
     ],
@@ -135,6 +141,7 @@
         "libnativewindow",
         "libcodec2_soft_common",
         "libsfplugin_ccodec_utils",
+        "libstagefright_aidl_bufferpool2",
         "libstagefright_foundation",
         "libstagefright_bufferpool@2.0.1",
         "libgralloctypes",
@@ -144,9 +151,13 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.bufferqueue@2.0",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.media.bufferpool2-V1-ndk",
     ],
 
     shared_libs: [
+        "libbinder_ndk",
         "libui",
         "libdl",
         "libvndksupport",
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 143355f..018e269 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -29,19 +29,21 @@
 #include <C2BlockInternal.h>
 #include <C2PlatformSupport.h>
 #include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
 
 namespace {
 
 using android::C2AllocatorBlob;
 using android::C2AllocatorGralloc;
 using android::C2AllocatorIon;
-using android::hardware::media::bufferpool::BufferPoolData;
+
+namespace bufferpool = android::hardware::media::bufferpool;
+namespace bufferpool_impl = android::hardware::media::bufferpool::V2_0::implementation;
 using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocation;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocator;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::INVALID_CONNECTIONID;
+
+namespace bufferpool2 = aidl::android::hardware::media::bufferpool2;
+namespace bufferpool2_impl = aidl::android::hardware::media::bufferpool2::implementation;
+using ResultStatus2 = aidl::android::hardware::media::bufferpool2::ResultStatus;
 
 // This anonymous namespace contains the helper classes that allow our implementation to create
 // block/buffer objects.
@@ -354,21 +356,21 @@
         return TYPE_BUFFERPOOL;
     }
 
-    void getBufferPoolData(std::shared_ptr<BufferPoolData> *data) const {
+    void getBufferPoolData(std::shared_ptr<bufferpool::BufferPoolData> *data) const {
         *data = mData;
     }
 
-    C2PooledBlockPoolData(const std::shared_ptr<BufferPoolData> &data) : mData(data) {}
+    C2PooledBlockPoolData(const std::shared_ptr<bufferpool::BufferPoolData> &data) : mData(data) {}
 
     virtual ~C2PooledBlockPoolData() override {}
 
 private:
-    std::shared_ptr<BufferPoolData> mData;
+    std::shared_ptr<bufferpool::BufferPoolData> mData;
 };
 
 bool _C2BlockFactory::GetBufferPoolData(
         const std::shared_ptr<const _C2BlockPoolData> &data,
-        std::shared_ptr<BufferPoolData> *bufferPoolData) {
+        std::shared_ptr<bufferpool::BufferPoolData> *bufferPoolData) {
     if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL) {
         const std::shared_ptr<const C2PooledBlockPoolData> poolData =
                 std::static_pointer_cast<const C2PooledBlockPoolData>(data);
@@ -378,6 +380,37 @@
     return false;
 }
 
+struct C2_HIDE C2PooledBlockPoolData2 : _C2BlockPoolData { // AIDL BufferPool(bufferpool2)
+
+    type_t getType() const override {
+        return TYPE_BUFFERPOOL2;
+    }
+
+    void getBufferPoolData(std::shared_ptr<bufferpool2::BufferPoolData> *data) const {
+        *data = mData;
+    }
+
+    C2PooledBlockPoolData2(const std::shared_ptr<bufferpool2::BufferPoolData> &data)
+            : mData(data) {}
+
+    virtual ~C2PooledBlockPoolData2() override {}
+
+private:
+    std::shared_ptr<bufferpool2::BufferPoolData> mData;
+};
+
+bool _C2BlockFactory::GetBufferPoolData(
+        const std::shared_ptr<const _C2BlockPoolData> &data,
+        std::shared_ptr<bufferpool2::BufferPoolData> *bufferPoolData) {
+    if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL2) {
+        const std::shared_ptr<const C2PooledBlockPoolData2> poolData =
+                std::static_pointer_cast<const C2PooledBlockPoolData2>(data);
+        poolData->getBufferPoolData(bufferPoolData);
+        return true;
+    }
+    return false;
+}
+
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
         const std::shared_ptr<C2LinearAllocation> &alloc,
         const std::shared_ptr<_C2BlockPoolData> &data, size_t offset, size_t size) {
@@ -422,7 +455,7 @@
 }
 
 std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
-        const C2Handle *cHandle, const std::shared_ptr<BufferPoolData> &data) {
+        const C2Handle *cHandle, const std::shared_ptr<bufferpool::BufferPoolData> &data) {
     // TODO: get proper allocator? and mutex?
     static std::shared_ptr<C2Allocator> sAllocator = []{
         std::shared_ptr<C2Allocator> allocator;
@@ -452,11 +485,43 @@
     return nullptr;
 };
 
+std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
+        const C2Handle *cHandle, const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
+    // TODO: get proper allocator? and mutex?
+    static std::shared_ptr<C2Allocator> sAllocator = []{
+        std::shared_ptr<C2Allocator> allocator;
+        std::shared_ptr<C2AllocatorStore> allocatorStore =
+                android::GetCodec2PlatformAllocatorStore();
+        allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+
+        return allocator;
+    }();
+
+    if (sAllocator == nullptr)
+        return nullptr;
+
+    bool isValidHandle = sAllocator->checkHandle(cHandle);
+
+    std::shared_ptr<C2LinearAllocation> alloc;
+    if (isValidHandle) {
+        c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
+        const std::shared_ptr<C2PooledBlockPoolData2> poolData =
+                std::make_shared<C2PooledBlockPoolData2>(data);
+        if (err == C2_OK && poolData) {
+            // TODO: config params?
+            std::shared_ptr<C2LinearBlock> block =
+                    _C2BlockFactory::CreateLinearBlock(alloc, poolData);
+            return block;
+        }
+    }
+    return nullptr;
+};
+
 /**
  * Wrapped C2Allocator which is injected to buffer pool on behalf of
  * C2BlockPool.
  */
-class _C2BufferPoolAllocator : public BufferPoolAllocator {
+class _C2BufferPoolAllocator : public bufferpool_impl::BufferPoolAllocator {
 public:
     _C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> &allocator)
         : mAllocator(allocator) {}
@@ -464,7 +529,7 @@
     ~_C2BufferPoolAllocator() override {}
 
     ResultStatus allocate(const std::vector<uint8_t> &params,
-                          std::shared_ptr<BufferPoolAllocation> *alloc,
+                          std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
                           size_t *allocSize) override;
 
     bool compatible(const std::vector<uint8_t> &newParams,
@@ -496,7 +561,7 @@
                           std::vector<uint8_t> *params);
 
     /**
-     * Transforms an existing native handle to an C2LinearAllcation.
+     * Transforms an existing native handle to a C2LinearAllocation.
      * Wrapper to C2Allocator#priorLinearAllocation
      */
     c2_status_t priorLinearAllocation(
@@ -504,7 +569,7 @@
             std::shared_ptr<C2LinearAllocation> *c2Allocation);
 
     /**
-     * Transforms an existing native handle to an C2GraphicAllcation.
+     * Transforms an existing native handle to a C2GraphicAllocation.
      * Wrapper to C2Allocator#priorGraphicAllocation
      */
     c2_status_t priorGraphicAllocation(
@@ -545,7 +610,7 @@
     LinearAllocationDtor(const std::shared_ptr<C2LinearAllocation> &alloc)
         : mAllocation(alloc) {}
 
-    void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+    void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
 
     const std::shared_ptr<C2LinearAllocation> mAllocation;
 };
@@ -554,14 +619,14 @@
     GraphicAllocationDtor(const std::shared_ptr<C2GraphicAllocation> &alloc)
         : mAllocation(alloc) {}
 
-    void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+    void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
 
     const std::shared_ptr<C2GraphicAllocation> mAllocation;
 };
 
 ResultStatus _C2BufferPoolAllocator::allocate(
         const std::vector<uint8_t>  &params,
-        std::shared_ptr<BufferPoolAllocation> *alloc,
+        std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
         size_t *allocSize) {
     AllocParams c2Params;
     memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
@@ -574,9 +639,10 @@
             status = mAllocator->newLinearAllocation(
                     c2Params.data.params[0], c2Params.data.usage, &c2Linear);
             if (status == C2_OK && c2Linear) {
-                BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Linear->handle());
+                bufferpool_impl::BufferPoolAllocation *ptr =
+                        new bufferpool_impl::BufferPoolAllocation(c2Linear->handle());
                 if (ptr) {
-                    *alloc = std::shared_ptr<BufferPoolAllocation>(
+                    *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
                             ptr, LinearAllocationDtor(c2Linear));
                     if (*alloc) {
                         *allocSize = (size_t)c2Params.data.params[0];
@@ -596,9 +662,10 @@
                     c2Params.data.params[2],
                     c2Params.data.usage, &c2Graphic);
             if (status == C2_OK && c2Graphic) {
-                BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Graphic->handle());
+                bufferpool_impl::BufferPoolAllocation *ptr =
+                        new bufferpool_impl::BufferPoolAllocation(c2Graphic->handle());
                 if (ptr) {
-                    *alloc = std::shared_ptr<BufferPoolAllocation>(
+                    *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
                             ptr, GraphicAllocationDtor(c2Graphic));
                     if (*alloc) {
                         *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
@@ -624,7 +691,7 @@
     memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
     memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
 
-    // TODO: support not exact matching. e.g) newCapacity < oldCapacity
+    // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
     if (newAlloc.data.allocType == oldAlloc.data.allocType &&
             newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
         for (int i = 0; i < kMaxIntParams; ++i) {
@@ -666,7 +733,7 @@
 public:
     Impl(const std::shared_ptr<C2Allocator> &allocator)
             : mInit(C2_OK),
-              mBufferPoolManager(ClientManager::getInstance()),
+              mBufferPoolManager(bufferpool_impl::ClientManager::getInstance()),
               mAllocator(std::make_shared<_C2BufferPoolAllocator>(allocator)) {
         if (mAllocator && mBufferPoolManager) {
             if (mBufferPoolManager->create(
@@ -692,7 +759,7 @@
         }
         std::vector<uint8_t> params;
         mAllocator->getLinearParams(capacity, usage, &params);
-        std::shared_ptr<BufferPoolData> bufferPoolData;
+        std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
         native_handle_t *cHandle = nullptr;
         ResultStatus status = mBufferPoolManager->allocate(
                 mConnectionId, params, &cHandle, &bufferPoolData);
@@ -725,7 +792,7 @@
         }
         std::vector<uint8_t> params;
         mAllocator->getGraphicParams(width, height, format, usage, &params);
-        std::shared_ptr<BufferPoolData> bufferPoolData;
+        std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
         native_handle_t *cHandle = nullptr;
         ResultStatus status = mBufferPoolManager->allocate(
                 mConnectionId, params, &cHandle, &bufferPoolData);
@@ -750,20 +817,340 @@
         return C2_CORRUPTED;
     }
 
-    ConnectionId getConnectionId() {
-        return mInit != C2_OK ? INVALID_CONNECTIONID : mConnectionId;
+    bufferpool_impl::ConnectionId getConnectionId() {
+        return mInit != C2_OK ? bufferpool_impl::INVALID_CONNECTIONID : mConnectionId;
     }
 
 private:
     c2_status_t mInit;
-    const android::sp<ClientManager> mBufferPoolManager;
-    ConnectionId mConnectionId; // locally
+    const android::sp<bufferpool_impl::ClientManager> mBufferPoolManager;
+    bufferpool_impl::ConnectionId mConnectionId; // locally
     const std::shared_ptr<_C2BufferPoolAllocator> mAllocator;
 };
 
+/**
+ * Wrapped C2Allocator which is injected to AIDL buffer pool on behalf of
+ * C2BlockPool.
+ */
+class _C2BufferPoolAllocator2 : public bufferpool2_impl::BufferPoolAllocator {
+public:
+    _C2BufferPoolAllocator2(const std::shared_ptr<C2Allocator> &allocator)
+        : mAllocator(allocator) {}
+
+    ~_C2BufferPoolAllocator2() override {}
+
+    bufferpool2_impl::BufferPoolStatus allocate(const std::vector<uint8_t> &params,
+                          std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
+                          size_t *allocSize) override;
+
+    bool compatible(const std::vector<uint8_t> &newParams,
+                    const std::vector<uint8_t> &oldParams) override;
+
+    // Methods for codec2 component (C2BlockPool).
+    /**
+     * Transforms linear allocation parameters for C2Allocator to parameters
+     * for buffer pool.
+     *
+     * @param capacity      size of linear allocation
+     * @param usage         memory usage pattern for linear allocation
+     * @param params        allocation parameters for buffer pool
+     */
+    void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
+                         std::vector<uint8_t> *params);
+
+    /**
+     * Transforms graphic allocation parameters for C2Allocator to parameters
+     * for buffer pool.
+     *
+     * @param width         width of graphic allocation
+     * @param height        height of graphic allocation
+     * @param format        color format of graphic allocation
+     * @param params        allocation parameter for buffer pool
+     */
+    void getGraphicParams(uint32_t width, uint32_t height,
+                          uint32_t format, C2MemoryUsage usage,
+                          std::vector<uint8_t> *params);
+
+    /**
+     * Transforms an existing native handle to a C2LinearAllocation.
+     * Wrapper to C2Allocator#priorLinearAllocation
+     */
+    c2_status_t priorLinearAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2LinearAllocation> *c2Allocation);
+
+    /**
+     * Transforms an existing native handle to a C2GraphicAllocation.
+     * Wrapper to C2Allocator#priorGraphicAllocation
+     */
+    c2_status_t priorGraphicAllocation(
+            const C2Handle *handle,
+            std::shared_ptr<C2GraphicAllocation> *c2Allocation);
+
+private:
+    static constexpr int kMaxIntParams = 5; // large enough number;
+
+    enum AllocType : uint8_t {
+        ALLOC_NONE = 0,
+
+        ALLOC_LINEAR,
+        ALLOC_GRAPHIC,
+    };
+
+    union AllocParams {
+        struct {
+            AllocType allocType;
+            C2MemoryUsage usage;
+            uint32_t params[kMaxIntParams];
+        } data;
+        uint8_t array[0];
+
+        AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
+        AllocParams(C2MemoryUsage usage, uint32_t capacity)
+            : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
+        AllocParams(
+                C2MemoryUsage usage,
+                uint32_t width, uint32_t height, uint32_t format)
+                : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
+    };
+
+    const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+struct LinearAllocationDtor2 {
+    LinearAllocationDtor2(const std::shared_ptr<C2LinearAllocation> &alloc)
+        : mAllocation(alloc) {}
+
+    void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+
+    const std::shared_ptr<C2LinearAllocation> mAllocation;
+};
+
+struct GraphicAllocationDtor2 {
+    GraphicAllocationDtor2(const std::shared_ptr<C2GraphicAllocation> &alloc)
+        : mAllocation(alloc) {}
+
+    void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+
+    const std::shared_ptr<C2GraphicAllocation> mAllocation;
+};
+
+bufferpool2_impl::BufferPoolStatus _C2BufferPoolAllocator2::allocate(
+        const std::vector<uint8_t>  &params,
+        std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
+        size_t *allocSize) {
+    AllocParams c2Params;
+    memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
+    c2_status_t status = C2_BAD_VALUE;
+    switch(c2Params.data.allocType) {
+        case ALLOC_NONE:
+            break;
+        case ALLOC_LINEAR: {
+            std::shared_ptr<C2LinearAllocation> c2Linear;
+            status = mAllocator->newLinearAllocation(
+                    c2Params.data.params[0], c2Params.data.usage, &c2Linear);
+            if (status == C2_OK && c2Linear) {
+                bufferpool2_impl::BufferPoolAllocation *ptr =
+                        new bufferpool2_impl::BufferPoolAllocation(c2Linear->handle());
+                if (ptr) {
+                    *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
+                            ptr, LinearAllocationDtor2(c2Linear));
+                    if (*alloc) {
+                        *allocSize = (size_t)c2Params.data.params[0];
+                        return ResultStatus2::OK;
+                    }
+                    delete ptr;
+                }
+                return ResultStatus2::NO_MEMORY;
+            }
+            break;
+        }
+        case ALLOC_GRAPHIC: {
+            std::shared_ptr<C2GraphicAllocation> c2Graphic;
+            status = mAllocator->newGraphicAllocation(
+                    c2Params.data.params[0],
+                    c2Params.data.params[1],
+                    c2Params.data.params[2],
+                    c2Params.data.usage, &c2Graphic);
+            if (status == C2_OK && c2Graphic) {
+                bufferpool2_impl::BufferPoolAllocation *ptr =
+                        new bufferpool2_impl::BufferPoolAllocation(c2Graphic->handle());
+                if (ptr) {
+                    *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
+                            ptr, GraphicAllocationDtor2(c2Graphic));
+                    if (*alloc) {
+                        *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
+                        return ResultStatus2::OK;
+                    }
+                    delete ptr;
+                }
+                return ResultStatus2::NO_MEMORY;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return ResultStatus2::CRITICAL_ERROR;
+}
+
+bool _C2BufferPoolAllocator2::compatible(
+        const std::vector<uint8_t>  &newParams,
+        const std::vector<uint8_t>  &oldParams) {
+    AllocParams newAlloc;
+    AllocParams oldAlloc;
+    memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
+    memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
+
+    // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
+    if (newAlloc.data.allocType == oldAlloc.data.allocType &&
+            newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
+        for (int i = 0; i < kMaxIntParams; ++i) {
+            if (newAlloc.data.params[i] != oldAlloc.data.params[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+void _C2BufferPoolAllocator2::getLinearParams(
+        uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
+    AllocParams c2Params(usage, capacity);
+    params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+void _C2BufferPoolAllocator2::getGraphicParams(
+        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+        std::vector<uint8_t> *params) {
+    AllocParams c2Params(usage, width, height, format);
+    params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+c2_status_t _C2BufferPoolAllocator2::priorLinearAllocation(
+        const C2Handle *handle,
+        std::shared_ptr<C2LinearAllocation> *c2Allocation) {
+    return mAllocator->priorLinearAllocation(handle, c2Allocation);
+}
+
+c2_status_t _C2BufferPoolAllocator2::priorGraphicAllocation(
+        const C2Handle *handle,
+        std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
+    return mAllocator->priorGraphicAllocation(handle, c2Allocation);
+}
+
+class C2PooledBlockPool::Impl2 {
+public:
+    Impl2(const std::shared_ptr<C2Allocator> &allocator)
+            : mInit(C2_OK),
+              mBufferPoolManager(bufferpool2_impl::ClientManager::getInstance()),
+              mAllocator(std::make_shared<_C2BufferPoolAllocator2>(allocator)) {
+        if (mAllocator && mBufferPoolManager) {
+            if (mBufferPoolManager->create(
+                    mAllocator, &mConnectionId) == ResultStatus2::OK) {
+                return;
+            }
+        }
+        mInit = C2_NO_INIT;
+    }
+
+    ~Impl2() {
+        if (mInit == C2_OK) {
+            mBufferPoolManager->close(mConnectionId);
+        }
+    }
+
+    c2_status_t fetchLinearBlock(
+            uint32_t capacity, C2MemoryUsage usage,
+            std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+        block->reset();
+        if (mInit != C2_OK) {
+            return mInit;
+        }
+        std::vector<uint8_t> params;
+        mAllocator->getLinearParams(capacity, usage, &params);
+        std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
+        native_handle_t *cHandle = nullptr;
+        bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
+                mConnectionId, params, &cHandle, &bufferPoolData);
+        if (status == ResultStatus2::OK) {
+            std::shared_ptr<C2LinearAllocation> alloc;
+            std::shared_ptr<C2PooledBlockPoolData2> poolData =
+                    std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
+            c2_status_t err = mAllocator->priorLinearAllocation(cHandle, &alloc);
+            if (err == C2_OK && poolData && alloc) {
+                *block = _C2BlockFactory::CreateLinearBlock(alloc, poolData, 0, capacity);
+                if (*block) {
+                    return C2_OK;
+                }
+            }
+            return C2_NO_MEMORY;
+        }
+        if (status == ResultStatus2::NO_MEMORY) {
+            return C2_NO_MEMORY;
+        }
+        return C2_CORRUPTED;
+    }
+
+    c2_status_t fetchGraphicBlock(
+            uint32_t width, uint32_t height, uint32_t format,
+            C2MemoryUsage usage,
+            std::shared_ptr<C2GraphicBlock> *block) {
+        block->reset();
+        if (mInit != C2_OK) {
+            return mInit;
+        }
+        std::vector<uint8_t> params;
+        mAllocator->getGraphicParams(width, height, format, usage, &params);
+        std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
+        native_handle_t *cHandle = nullptr;
+        bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
+                mConnectionId, params, &cHandle, &bufferPoolData);
+        if (status == ResultStatus2::OK) {
+            std::shared_ptr<C2GraphicAllocation> alloc;
+            std::shared_ptr<C2PooledBlockPoolData2> poolData =
+                std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
+            c2_status_t err = mAllocator->priorGraphicAllocation(
+                    cHandle, &alloc);
+            if (err == C2_OK && poolData && alloc) {
+                *block = _C2BlockFactory::CreateGraphicBlock(
+                        alloc, poolData, C2Rect(width, height));
+                if (*block) {
+                    return C2_OK;
+                }
+            }
+            return C2_NO_MEMORY;
+        }
+        if (status == ResultStatus2::NO_MEMORY) {
+            return C2_NO_MEMORY;
+        }
+        return C2_CORRUPTED;
+    }
+
+    bufferpool2_impl::ConnectionId getConnectionId() {
+        return mInit != C2_OK ? bufferpool2_impl::INVALID_CONNECTIONID : mConnectionId;
+    }
+
+private:
+    c2_status_t mInit;
+    const std::shared_ptr<bufferpool2_impl::ClientManager> mBufferPoolManager;
+    bufferpool2_impl::ConnectionId mConnectionId; // locally
+    const std::shared_ptr<_C2BufferPoolAllocator2> mAllocator;
+};
+
 C2PooledBlockPool::C2PooledBlockPool(
-        const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
-        : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
+        const std::shared_ptr<C2Allocator> &allocator,
+        const local_id_t localId,
+        BufferPoolVer ver)
+        : mAllocator(allocator), mLocalId(localId), mBufferPoolVer(ver) {
+        if (mBufferPoolVer == VER_HIDL) {
+            mImpl = std::make_unique<Impl>(allocator);
+        }
+        if (mBufferPoolVer == VER_AIDL2) {
+            mImpl2 = std::make_unique<Impl2>(allocator);
+        }
+    }
 
 C2PooledBlockPool::~C2PooledBlockPool() {
 }
@@ -772,9 +1159,12 @@
         uint32_t capacity,
         C2MemoryUsage usage,
         std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
-    if (mImpl) {
+    if (mBufferPoolVer == VER_HIDL && mImpl) {
         return mImpl->fetchLinearBlock(capacity, usage, block);
     }
+    if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+        return mImpl2->fetchLinearBlock(capacity, usage, block);
+    }
     return C2_CORRUPTED;
 }
 
@@ -784,16 +1174,22 @@
         uint32_t format,
         C2MemoryUsage usage,
         std::shared_ptr<C2GraphicBlock> *block) {
-    if (mImpl) {
+    if (mBufferPoolVer == VER_HIDL && mImpl) {
         return mImpl->fetchGraphicBlock(width, height, format, usage, block);
     }
+    if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+        return mImpl2->fetchGraphicBlock(width, height, format, usage, block);
+    }
     return C2_CORRUPTED;
 }
 
 int64_t C2PooledBlockPool::getConnectionId() {
-    if (mImpl) {
+    if (mBufferPoolVer == VER_HIDL && mImpl) {
         return mImpl->getConnectionId();
     }
+    if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+        return mImpl2->getConnectionId();
+    }
     return 0;
 }
 
@@ -1128,7 +1524,7 @@
 
 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
         const C2Handle *cHandle,
-        const std::shared_ptr<BufferPoolData> &data) {
+        const std::shared_ptr<bufferpool::BufferPoolData> &data) {
     // TODO: get proper allocator? and mutex?
     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
 
@@ -1147,6 +1543,26 @@
     return nullptr;
 };
 
+std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
+        const C2Handle *cHandle,
+        const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
+    // TODO: get proper allocator? and mutex?
+    static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
+
+    std::shared_ptr<C2GraphicAllocation> alloc;
+    if (sAllocator->isValid(cHandle)) {
+        c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
+        const std::shared_ptr<C2PooledBlockPoolData2> poolData =
+                std::make_shared<C2PooledBlockPoolData2>(data);
+        if (err == C2_OK && poolData) {
+            // TODO: config setup?
+            std::shared_ptr<C2GraphicBlock> block =
+                    _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
+            return block;
+        }
+    }
+    return nullptr;
+};
 
 /* ========================================== BUFFER ========================================= */
 
diff --git a/media/codec2/vndk/include/C2BufferPriv.h b/media/codec2/vndk/include/C2BufferPriv.h
index be5f69c..527845f 100644
--- a/media/codec2/vndk/include/C2BufferPriv.h
+++ b/media/codec2/vndk/include/C2BufferPriv.h
@@ -74,7 +74,14 @@
 
 class C2PooledBlockPool : public C2BlockPool {
 public:
-    C2PooledBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
+    enum BufferPoolVer : int {
+        VER_HIDL = 0,
+        VER_AIDL2
+    };
+    C2PooledBlockPool(
+            const std::shared_ptr<C2Allocator> &allocator,
+            const local_id_t localId,
+            BufferPoolVer ver = VER_HIDL);
 
     virtual ~C2PooledBlockPool() override;
 
@@ -117,9 +124,12 @@
 private:
     const std::shared_ptr<C2Allocator> mAllocator;
     const local_id_t mLocalId;
+    const BufferPoolVer mBufferPoolVer;
 
-    class Impl;
+    class Impl; // HIDL BufferPool VER_HIDL
     std::unique_ptr<Impl> mImpl;
+    class Impl2; // AIDL BufferPool(bufferpool2) VER_AIDL2
+    std::unique_ptr<Impl2> mImpl2;
 };
 
 #endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index c510fca..fe5390a 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -21,17 +21,22 @@
 
 #include <C2Buffer.h>
 
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
+// Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
+namespace android::hardware::media::bufferpool {
 
+// BuffePool Data for HIDL-BufferPool
 struct BufferPoolData;
 
 }
+namespace aidl::android::hardware::media::bufferpool2 {
+
+// BuffePool Data for AIDL-BufferPool
+struct BufferPoolData;
+
 }
-}
-}
+
+using bufferpool_BufferPoolData = android::hardware::media::bufferpool::BufferPoolData;
+using bufferpool2_BufferPoolData = aidl::android::hardware::media::bufferpool2::BufferPoolData;
 
 /**
  * Stores informations from C2BlockPool implementations which are required by C2Block.
@@ -40,6 +45,7 @@
     enum type_t : int {
         TYPE_BUFFERPOOL = 0,
         TYPE_BUFFERQUEUE,
+        TYPE_BUFFERPOOL2, // AIDL-BufferPool
     };
 
     virtual type_t getType() const = 0;
@@ -136,6 +142,7 @@
     std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
             const C2Handle *handle);
 
+    // HIDL-BufferPool
     /**
      * Create a linear block from the received bufferpool data.
      *
@@ -147,7 +154,7 @@
     static
     std::shared_ptr<C2LinearBlock> CreateLinearBlock(
             const C2Handle *handle,
-            const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data);
+            const std::shared_ptr<bufferpool_BufferPoolData> &data);
 
     /**
      * Create a graphic block from the received bufferpool data.
@@ -160,7 +167,7 @@
     static
     std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
             const C2Handle *handle,
-            const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data);
+            const std::shared_ptr<bufferpool_BufferPoolData> &data);
 
     /**
      * Get bufferpool data from the blockpool data.
@@ -174,7 +181,48 @@
     static
     bool GetBufferPoolData(
             const std::shared_ptr<const _C2BlockPoolData> &poolData,
-            std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> *bufferPoolData);
+            std::shared_ptr<bufferpool_BufferPoolData> *bufferPoolData);
+
+    // AIDL-BufferPool
+    /**
+     * Create a linear block from the received bufferpool data.
+     *
+     * \param data  bufferpool data to a linear block
+     *
+     * \return shared pointer to the linear block. nullptr if there was not enough memory to
+     *         create this block.
+     */
+    static
+    std::shared_ptr<C2LinearBlock> CreateLinearBlock(
+            const C2Handle *handle,
+            const std::shared_ptr<bufferpool2_BufferPoolData> &data);
+
+    /**
+     * Create a graphic block from the received bufferpool data.
+     *
+     * \param data  bufferpool data to a graphic block
+     *
+     * \return shared pointer to the graphic block. nullptr if there was not enough memory to
+     *         create this block.
+     */
+    static
+    std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
+            const C2Handle *handle,
+            const std::shared_ptr<bufferpool2_BufferPoolData> &data);
+
+    /**
+     * Get bufferpool data from the blockpool data.
+     *
+     * \param poolData          blockpool data
+     * \param bufferPoolData    pointer to bufferpool data where the bufferpool
+     *                          data is stored.
+     *
+     * \return {\code true} when there is valid bufferpool data, {\code false} otherwise.
+     */
+    static
+    bool GetBufferPoolData(
+            const std::shared_ptr<const _C2BlockPoolData> &poolData,
+            std::shared_ptr<bufferpool2_BufferPoolData> *bufferPoolData);
 
     /*
      * Life Cycle Management of BufferQueue-Based Blocks
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 5ea4926..68a8590 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1091,80 +1091,6 @@
     return convertReinterpret<int32_t>(legacy);
 }
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
-    switch (aidl) {
-        case media::AudioDualMonoMode::OFF:
-            return AUDIO_DUAL_MONO_MODE_OFF;
-        case media::AudioDualMonoMode::LR:
-            return AUDIO_DUAL_MONO_MODE_LR;
-        case media::AudioDualMonoMode::LL:
-            return AUDIO_DUAL_MONO_MODE_LL;
-        case media::AudioDualMonoMode::RR:
-            return AUDIO_DUAL_MONO_MODE_RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_DUAL_MONO_MODE_OFF:
-            return media::AudioDualMonoMode::OFF;
-        case AUDIO_DUAL_MONO_MODE_LR:
-            return media::AudioDualMonoMode::LR;
-        case AUDIO_DUAL_MONO_MODE_LL:
-            return media::AudioDualMonoMode::LL;
-        case AUDIO_DUAL_MONO_MODE_RR:
-            return media::AudioDualMonoMode::RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
-    audio_playback_rate_t legacy;
-    legacy.mSpeed = aidl.speed;
-    legacy.mPitch = aidl.pitch;
-    legacy.mFallbackMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
-    legacy.mStretchMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
-    return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
-    media::AudioPlaybackRate aidl;
-    aidl.speed = legacy.mSpeed;
-    aidl.pitch = legacy.mPitch;
-    aidl.fallbackMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
-    aidl.stretchMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
-    return aidl;
-}
-
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
         const media::TrackSecondaryOutputInfo& aidl) {
@@ -1237,25 +1163,4 @@
             indexToEnum_bitmask<audio_direct_mode_t>,
             enumToMask_index<int32_t, media::AudioDirectMode>);
 }
-
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
-    switch (aidl) {
-        case media::LatencyMode::FREE:
-            return AUDIO_LATENCY_MODE_FREE;
-        case media::LatencyMode::LOW:
-            return AUDIO_LATENCY_MODE_LOW;
-    }
-    return unexpected(BAD_VALUE);
-}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_LATENCY_MODE_FREE:
-            return media::LatencyMode::FREE;
-        case AUDIO_LATENCY_MODE_LOW:
-            return media::LatencyMode::LOW;
-    }
-    return unexpected(BAD_VALUE);
-}
 }  // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4679731..9ddae1e 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -281,14 +281,12 @@
         "aidl/android/media/AudioAttributesInternal.aidl",
         "aidl/android/media/AudioClient.aidl",
         "aidl/android/media/AudioDirectMode.aidl",
-        "aidl/android/media/AudioDualMonoMode.aidl",
         "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainSys.aidl",
         "aidl/android/media/AudioHalVersion.aidl",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioPatchFw.aidl",
-        "aidl/android/media/AudioPlaybackRate.aidl",
         "aidl/android/media/AudioPortFw.aidl",
         "aidl/android/media/AudioPortSys.aidl",
         "aidl/android/media/AudioPortConfigFw.aidl",
@@ -303,7 +301,6 @@
         "aidl/android/media/AudioUniqueIdUse.aidl",
         "aidl/android/media/AudioVibratorInfo.aidl",
         "aidl/android/media/EffectDescriptor.aidl",
-        "aidl/android/media/LatencyMode.aidl",
         "aidl/android/media/TrackSecondaryOutputInfo.aidl",
     ],
     imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 5a1dc64..ad03711 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -672,12 +672,12 @@
 }
 
 Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
-        int output, const std::vector<media::LatencyMode>& latencyModes) {
+        int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(
-                    latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+                    latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
 
     std::vector<sp<SupportedLatencyModesCallback>> callbacks;
     {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 22bd2a3..9386b9b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1266,7 +1266,7 @@
 status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
 {
     AutoMutex lock(mLock);
-    media::AudioDualMonoMode mediaMode;
+    media::audio::common::AudioDualMonoMode mediaMode;
     const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
     if (status == NO_ERROR) {
         *mode = VALUE_OR_RETURN_STATUS(
@@ -1381,7 +1381,7 @@
 {
     AutoMutex lock(mLock);
     if (isOffloadedOrDirect_l()) {
-        media::AudioPlaybackRate playbackRateTemp;
+        media::audio::common::AudioPlaybackRate playbackRateTemp;
         const status_t status = statusTFromBinderStatus(
                 mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
         if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index d895f80..30ccefe 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -822,8 +822,8 @@
 status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
         audio_io_handle_t output, audio_latency_mode_t mode) {
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
-    media::LatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+    media::audio::common::AudioLatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
     return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
 }
 
@@ -834,14 +834,14 @@
     }
 
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl;
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
 
     *modes = VALUE_OR_RETURN_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
-                     aidl2legacy_LatencyMode_audio_latency_mode_t));
+                     aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
 
     return NO_ERROR;
 }
@@ -1377,17 +1377,17 @@
 }
 
 Status AudioFlingerServerAdapter::setRequestedLatencyMode(
-        int32_t output, media::LatencyMode modeAidl) {
+        int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
-            aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+            aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
     return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
             outputLegacy, modeLegacy));
 }
 
 Status AudioFlingerServerAdapter::getSupportedLatencyModes(
-        int output, std::vector<media::LatencyMode>* _aidl_return) {
+        int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy;
@@ -1395,8 +1395,8 @@
     RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
 
     *_aidl_return = VALUE_OR_RETURN_BINDER(
-            convertContainer<std::vector<media::LatencyMode>>(
-                    modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+            convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                    modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
     return Status::ok();
 }
 
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
-    OFF = 0,
-    LR = 1,
-    LL = 2,
-    RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- *       As this is used for native wire serialization, no need to define
- *       audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- *       until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
-    /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float speed;
-    /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float pitch;
-    /** Interpreted as audio_timestretch_stretch_mode_t */
-    int stretchMode;
-    /** Interpreted as audio_timestretch_fallback_mode_t */
-    int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
 
 import android.media.AudioIoConfigEvent;
 import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
 
 /**
  * A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
     /**
      * Called when the latency modes supported on a given output stream change.
      * output is the I/O handle of the output stream for which the change is signalled.
-     * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+     * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
      */
-    oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+    oneway void onSupportedLatencyModesChanged(
+            int output, in AudioLatencyMode[] latencyModes);
 }
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7deb384..69810c0 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -37,12 +37,12 @@
 import android.media.IAudioTrack;
 import android.media.ISoundDose;
 import android.media.ISoundDoseCallback;
-import android.media.LatencyMode;
 import android.media.MicrophoneInfoData;
 import android.media.RenderPosition;
 import android.media.TrackSecondaryOutputInfo;
 import android.media.audio.common.AudioChannelLayout;
 import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
 import android.media.audio.common.AudioMMapPolicyInfo;
 import android.media.audio.common.AudioMMapPolicyType;
 import android.media.audio.common.AudioMode;
@@ -230,21 +230,21 @@
     void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
 
     /**
-     * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+     * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
      * This can be used when some use case on a given mixer/stream can only be enabled
      * if a specific latency mode is selected on the audio path below the HAL.
      * For instance spatial audio with head tracking.
      * output is the I/O handle of the output stream for which the request is made.
      * latencyMode is the requested latency mode.
      */
-     void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+     void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
 
     /**
      * Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
      * output is the I/O handle of the output stream to which the query applies.
      * returns the list of supported latency modes.
      */
-    LatencyMode[] getSupportedLatencyModes(int output);
+    AudioLatencyMode[] getSupportedLatencyModes(int output);
 
     /**
      * Requests if the implementation supports controlling the latency modes
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
 
 package android.media;
 
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
 import android.media.AudioTimestampInternal;
 import android.media.SharedFileRegion;
 import android.media.VolumeShaperConfiguration;
 import android.media.VolumeShaperOperation;
 import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
 
 /**
  * Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
-    /** No specific constraint on the latency */
-    FREE = 0,
-    /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
-    LOW = 1,
-}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index ff3598f..a1012a1 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,18 +24,15 @@
 #include <android/media/AudioAttributesInternal.h>
 #include <android/media/AudioClient.h>
 #include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
 #include <android/media/AudioFlag.h>
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
 #include <android/media/AudioPortFw.h>
 #include <android/media/AudioPortConfigFw.h>
 #include <android/media/AudioPortDeviceExtSys.h>
 #include <android/media/AudioTimestampInternal.h>
 #include <android/media/AudioUniqueIdUse.h>
 #include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
 #include <android/media/TrackSecondaryOutputInfo.h>
 
 #include <android/media/SharedFileRegion.h>
@@ -184,26 +181,6 @@
 ConversionResult<int32_t>
 legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
 using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -220,9 +197,4 @@
 ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
 
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
-
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 5ed8219..fedf511 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -778,7 +778,8 @@
                 const media::AudioIoDescriptor& ioDesc) override;
 
         binder::Status onSupportedLatencyModesChanged(
-                int output, const std::vector<media::LatencyMode>& latencyModes) override;
+                int output,
+                const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
 
         status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                                audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index fdf3113..6b6c407 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -709,9 +709,10 @@
     Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
     Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
-    Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+    Status setRequestedLatencyMode(
+            int output, media::audio::common::AudioLatencyMode mode) override;
     Status getSupportedLatencyModes(int output,
-            std::vector<media::LatencyMode>* _aidl_return) override;
+            std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
     Status setBluetoothVariableLatencyEnabled(bool enabled) override;
     Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
     Status supportsBluetoothVariableLatency(bool* support) override;
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 9e663bc..75d576e 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -391,7 +391,8 @@
     EXPECT_EQ(initial, convBack.value());
 }
 INSTANTIATE_TEST_SUITE_P(AudioStandard, AudioStandardRoundTripTest,
-                         testing::Values(AudioStandard::NONE, AudioStandard::EDID));
+                         testing::Values(AudioStandard::NONE, AudioStandard::EDID,
+                                         AudioStandard::SADB, AudioStandard::VSADB));
 
 class AudioEncapsulationMetadataTypeRoundTripTest
     : public testing::TestWithParam<AudioEncapsulationMetadataType> {};
@@ -450,7 +451,11 @@
         ExtraAudioDescriptor, ExtraAudioDescriptorRoundTripTest,
         testing::Values(std::make_tuple(AudioStandard::NONE, AudioEncapsulationType::NONE),
                         std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::NONE),
-                        std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937)));
+                        std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937),
+                        std::make_tuple(AudioStandard::SADB, AudioEncapsulationType::NONE),
+                        std::make_tuple(AudioStandard::SADB, AudioEncapsulationType::IEC61937),
+                        std::make_tuple(AudioStandard::VSADB, AudioEncapsulationType::NONE),
+                        std::make_tuple(AudioStandard::VSADB, AudioEncapsulationType::IEC61937)));
 
 TEST(AudioPortSessionExtRoundTripTest, Aidl2Legacy2Aidl) {
     const int32_t initial = 7;
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 41d4e16..4b6d5f2 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -24,6 +24,7 @@
 
     defaults: [
         "latest_android_media_audio_common_types_cpp_shared",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
     ],
 
     srcs: [
@@ -76,6 +77,7 @@
         "libutils",
         "liblog",
         "libbinder",
+        "libbinder_ndk",
         "libaudioclient",
         "libaudiomanager",
         "libmedialogservice",
@@ -105,11 +107,11 @@
         "libaudiohal_headers",
         "libaudioutils_headers",
         "libmedia_headers",
-        "libsounddose_headers",
     ],
 
     export_shared_lib_headers: [
         "libpermission",
+        "android.hardware.audio.sounddose-V1-ndk",
     ],
 
     cflags: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d3453f5..d930fb5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2220,9 +2220,9 @@
 void AudioFlinger::onSupportedLatencyModesChanged(
         audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
     int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
-                convertContainer<std::vector<media::LatencyMode>>(modes,
-                        legacy2aidl_audio_latency_mode_t_LatencyMode));
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+                convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                        modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
 
     Mutex::Autolock _l(mClientLock);
     size_t size = mNotificationClients.size();
@@ -2573,6 +2573,9 @@
         ALOGE("loadHwModule() error %d loading module %s", rc, name);
         return AUDIO_MODULE_HANDLE_NONE;
     }
+    if (!mMelReporter->activateHalSoundDoseComputation(name)) {
+        ALOGW("loadHwModule() sound dose reporting is not available");
+    }
 
     mHardwareStatus = AUDIO_HW_INIT;
     rc = dev->initCheck();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6dd1cda..173f0c9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <limits.h>
 
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
 #include <android/media/BnAudioTrack.h>
 #include <android/media/IAudioFlingerClient.h>
 #include <android/media/IAudioTrackCallback.h>
@@ -701,14 +702,16 @@
         binder::Status getVolumeShaperState(
                 int32_t id,
                 std::optional<media::VolumeShaperState>* _aidl_return) override;
-        binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
-        binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+        binder::Status getDualMonoMode(
+                media::audio::common::AudioDualMonoMode* _aidl_return) override;
+        binder::Status setDualMonoMode(
+                media::audio::common::AudioDualMonoMode mode) override;
         binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
         binder::Status setAudioDescriptionMixLevel(float leveldB) override;
         binder::Status getPlaybackRateParameters(
-                media::AudioPlaybackRate* _aidl_return) override;
+                media::audio::common::AudioPlaybackRate* _aidl_return) override;
         binder::Status setPlaybackRateParameters(
-                const media::AudioPlaybackRate& playbackRate) override;
+                const media::audio::common::AudioPlaybackRate& playbackRate) override;
 
     private:
         const sp<PlaybackThread::Track> mTrack;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index b2e8027..b185959 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -22,12 +22,85 @@
 
 #include <android/media/ISoundDoseCallback.h>
 #include <audio_utils/power.h>
+#include <android/binder_manager.h>
 #include <utils/Log.h>
 
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
 namespace android {
 
+constexpr std::string_view kSoundDoseInterfaceModule = "/default";
+
+bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
+    if (mSoundDoseManager->forceUseFrameworkMel()) {
+        ALOGD("%s: Forcing use of internal MEL computation.", __func__);
+        activateInternalSoundDoseComputation();
+        return false;
+    }
+
+    if (mSoundDoseFactory == nullptr) {
+        ALOGW("%s: sound dose HAL reporting not available", __func__);
+        activateInternalSoundDoseComputation();
+        return false;
+    }
+
+    std::shared_ptr<ISoundDose> soundDoseInterface;
+    auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
+    if (!result.isOk()) {
+        ALOGW("%s: HAL cannot provide sound dose interface for module %s",
+              __func__, module.c_str());
+        activateInternalSoundDoseComputation();
+        return false;
+    }
+
+    if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+        ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
+        activateInternalSoundDoseComputation();
+        return false;
+    }
+
+    std::lock_guard _l(mLock);
+    mUseHalSoundDoseInterface = true;
+    stopInternalMelComputation();
+    return true;
+}
+
+void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+    {
+        std::lock_guard _l(mLock);
+        if (!mUseHalSoundDoseInterface) {
+            // no need to start internal MEL on active patches
+            return;
+        }
+        mUseHalSoundDoseInterface = false;
+    }
+
+    mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+
+    for (const auto& activePatches : mActiveMelPatches) {
+        for (const auto& deviceId : activePatches.second.deviceHandles) {
+            startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
+        }
+    }
+}
+
+void AudioFlinger::MelReporter::onFirstRef() {
+    mAudioFlinger.mPatchCommandThread->addListener(this);
+
+    std::string interface =
+        std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
+    AIBinder* binder = AServiceManager_checkService(interface.c_str());
+    if (binder == nullptr) {
+        ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
+        return;
+    }
+
+    mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
+}
+
 bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
-    if (mSoundDoseManager.computeCsdOnAllDevices()) {
+    if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
         return true;
     }
 
@@ -65,17 +138,17 @@
             && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
             audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
             newPatch.deviceHandles.push_back(deviceId);
+            AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
+                                    patch.mAudioPatch.sinks[i].ext.device.address};
+            mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
 
-            // Start the MEL calculation in the PlaybackThread
-            std::lock_guard _lAf(mAudioFlinger.mLock);
-            auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
-            if (thread != nullptr) {
-                thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
-                    deviceId,
-                    newPatch.streamHandle,
-                    thread->mSampleRate,
-                    thread->mChannelCount,
-                    thread->mFormat));
+            bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
+            {
+                std::lock_guard _l(mLock);
+                useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
+            }
+            if (!useHalSoundDoseInterface) {
+                startMelComputationForNewPatch(streamHandle, deviceId);
             }
         }
     }
@@ -84,6 +157,21 @@
     mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
 }
 
+void AudioFlinger::MelReporter::startMelComputationForNewPatch(
+        audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
+    // Start the MEL calculation in the PlaybackThread
+    std::lock_guard _lAf(mAudioFlinger.mLock);
+    auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
+    if (thread != nullptr) {
+        thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
+            deviceId,
+            streamHandle,
+            thread->mSampleRate,
+            thread->mChannelCount,
+            thread->mFormat));
+    }
+}
+
 void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
     ALOGV("%s", __func__);
 
@@ -103,25 +191,47 @@
         mActiveMelPatches.erase(patchIt);
     }
 
-    // Stop MEL calculation for the PlaybackThread
-    std::lock_guard _lAf(mAudioFlinger.mLock);
-    mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
-    auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
-    if (thread != nullptr) {
-        thread->stopMelComputation();
+    for (const auto& deviceId : melPatch.deviceHandles) {
+        mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
     }
+    stopInternalMelComputationForStream(melPatch.streamHandle);
 }
 
 sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
         const sp<media::ISoundDoseCallback>& callback) {
     // no need to lock since getSoundDoseInterface is synchronized
-    return mSoundDoseManager.getSoundDoseInterface(callback);
+    return mSoundDoseManager->getSoundDoseInterface(callback);
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputation() {
+    ALOGV("%s", __func__);
+    std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
+    {
+        std::lock_guard _l(mLock);
+        activePatchesCopy = mActiveMelPatches;
+        mActiveMelPatches.clear();
+    }
+
+    for (const auto& activePatch : activePatchesCopy) {
+        stopInternalMelComputationForStream(activePatch.second.streamHandle);
+    }
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
+    ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+
+    std::lock_guard _lAf(mAudioFlinger.mLock);
+    mSoundDoseManager->removeStreamProcessor(streamId);
+    auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+    if (thread != nullptr) {
+        thread->stopMelComputation();
+    }
 }
 
 std::string AudioFlinger::MelReporter::dump() {
     std::lock_guard _l(mLock);
     std::string output("\nSound Dose:\n");
-    output.append(mSoundDoseManager.dump());
+    output.append(mSoundDoseManager->dump());
     return output;
 }
 
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index b1abc59..acbc8ed 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -32,17 +32,34 @@
 class MelReporter : public PatchCommandThread::PatchCommandListener {
 public:
     explicit MelReporter(AudioFlinger& audioFlinger)
-        : mAudioFlinger(audioFlinger) {}
+        : mAudioFlinger(audioFlinger),
+          mSoundDoseManager(sp<SoundDoseManager>::make()) {}
 
-    void onFirstRef() override {
-        mAudioFlinger.mPatchCommandThread->addListener(this);
-    }
+    void onFirstRef() override;
 
     /** Returns true if we should compute MEL for the given device. */
     bool shouldComputeMelForDeviceType(audio_devices_t device);
 
-    // For now only support internal MelReporting
-    [[nodiscard]] bool isHalReportingEnabled() const { return false; }
+    /**
+     * Activates the MEL reporting from the HAL sound dose interface. If the HAL
+     * does not support the sound dose interface for this module, the internal MEL
+     * calculation will be use.
+     *
+     * For now support internal MelReporting only if the sound dose standalone HAL
+     * is not implemented
+     *
+     * @return true if the MEL reporting will be done from the sound dose HAL
+     * interface
+     */
+    bool activateHalSoundDoseComputation(const std::string& module);
+
+    /**
+     * Activates the MEL reporting from internal framework values. These are used
+     * as a fallback when there is no sound dose interface implementation from HAL.
+     * Note: the internal CSD computation does not guarantee a certification with
+     * IEC62368-1 3rd edition or EN50332-3
+     */
+    void activateInternalSoundDoseComputation();
 
     sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
@@ -54,9 +71,17 @@
     void onReleaseAudioPatch(audio_patch_handle_t handle) override;
 
 private:
-    AudioFlinger& mAudioFlinger;  // does not own the object
+    void stopInternalMelComputation();
+    void stopInternalMelComputationForStream(audio_io_handle_t streamId);
 
-    SoundDoseManager mSoundDoseManager;
+    void startMelComputationForNewPatch(audio_io_handle_t streamHandle,
+                                        audio_port_handle_t deviceId);
+
+    AudioFlinger& mAudioFlinger;  // does not own the object
+    std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory>
+        mSoundDoseFactory;
+
+    sp<SoundDoseManager> mSoundDoseManager;
 
     struct ActiveMelPatch {
         audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -70,4 +95,5 @@
     std::mutex mLock;
     std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
         mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
+    bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
 };
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9598ed9..3dcf932 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -273,8 +273,8 @@
 
 static std::string toString(audio_latency_mode_t mode) {
     // We convert to the AIDL type to print (eventually the legacy type will be removed).
-    const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
-    return result.has_value() ? media::toString(*result) : "UNKNOWN";
+    const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+    return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
 }
 
 // Could be made a template, but other toString overloads for std::vector are confused.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ac863b5..382e4f9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -440,7 +440,8 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+        media::audio::common::AudioDualMonoMode* _aidl_return)
 {
     audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
     const status_t status = mTrack->getDualMonoMode(&mode)
@@ -453,7 +454,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setDualMonoMode(
-        media::AudioDualMonoMode mode)
+        media::audio::common::AudioDualMonoMode mode)
 {
     const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -477,7 +478,7 @@
 }
 
 Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
-        media::AudioPlaybackRate* _aidl_return)
+        media::audio::common::AudioPlaybackRate* _aidl_return)
 {
     audio_playback_rate_t localPlaybackRate{};
     status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -490,7 +491,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
-        const media::AudioPlaybackRate& playbackRate)
+        const media::audio::common::AudioPlaybackRate& playbackRate)
 {
     const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -792,7 +793,7 @@
                         "  Format Chn mask  SRate "
                         "ST Usg CT "
                         " G db  L dB  R dB  VS dB "
-                        "  Server FrmCnt  FrmRdy F Underruns  Flushed"
+                        "  Server FrmCnt  FrmRdy F Underruns  Flushed BitPerfect"
                         "%s\n",
                         isServerLatencySupported() ? "   Latency" : "");
 }
@@ -878,7 +879,7 @@
                         "%08X %08X %6u "
                         "%2u %3x %2x "
                         "%5.2g %5.2g %5.2g %5.2g%c "
-                        "%08X %6zu%c %6zu %c %9u%c %7u",
+                        "%08X %6zu%c %6zu %c %9u%c %7u %10s",
             active ? "yes" : "no",
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
@@ -907,7 +908,8 @@
             fillingStatus,
             mAudioTrackServerProxy->getUnderrunFrames(),
             nowInUnderrun,
-            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000
+            (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
+            isBitPerfect() ? "true" : "false"
             );
 
     if (isServerLatencySupported()) {
@@ -1160,6 +1162,23 @@
     }
     if (status == NO_ERROR) {
         forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+
+        // send format to AudioManager for playback activity monitoring
+        sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
+        if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
+            std::unique_ptr<os::PersistableBundle> bundle =
+                    std::make_unique<os::PersistableBundle>();
+        bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
+                           isSpatialized());
+        bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
+        bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
+        status_t result = audioManager->portEvent(mPortId,
+                                                  PLAYER_UPDATE_FORMAT, bundle);
+        if (result != OK) {
+            ALOGE("%s: unable to send playback format for port ID %d, status error %d",
+                  __func__, mPortId, result);
+        }
+      }
     }
     return status;
 }
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
index 0e409d3..6d9a0cc 100644
--- a/services/audioflinger/sounddose/Android.bp
+++ b/services/audioflinger/sounddose/Android.bp
@@ -12,15 +12,24 @@
 
     double_loadable: true,
 
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "latest_android_hardware_audio_sounddose_ndk_shared",
+    ],
+
     srcs: [
         "SoundDoseManager.cpp",
     ],
 
     shared_libs: [
         "audioflinger-aidl-cpp",
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudiofoundation",
         "libaudioutils",
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "liblog",
         "libutils",
     ],
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 61f27cb..df6eb5b 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -20,14 +20,22 @@
 
 #include "SoundDoseManager.h"
 
+#if !defined(BACKEND_NDK)
+#define BACKEND_NDK
+#endif
+
+#include "android/media/SoundDoseRecord.h"
 #include <android-base/stringprintf.h>
+#include <media/AidlConversionCppNdk.h>
+#include <cinttypes>
 #include <time.h>
 #include <utils/Log.h>
-#include <cinttypes>
-#include "android/media/SoundDoseRecord.h"
 
 namespace android {
 
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
 namespace {
 
 int64_t getMonotonicSecond() {
@@ -46,6 +54,11 @@
         size_t channelCount, audio_format_t format) {
     std::lock_guard _l(mLock);
 
+    if (mHalSoundDose != nullptr) {
+        ALOGW("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
+        return nullptr;
+    }
+
     auto streamProcessor = mActiveProcessors.find(streamHandle);
     sp<audio_utils::MelProcessor> processor;
     if (streamProcessor != mActiveProcessors.end() &&
@@ -63,11 +76,54 @@
     }
 }
 
+bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+    ALOGV("%s", __func__);
+
+    {
+        std::lock_guard _l(mLock);
+
+        mHalSoundDose = halSoundDose;
+        if (halSoundDose == nullptr) {
+            ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+            return false;
+        }
+
+        if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+            ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
+                  __func__,
+                  mRs2Value);
+        }
+
+        // initialize the HAL sound dose callback lazily
+        if (mHalSoundDoseCallback == nullptr) {
+            mHalSoundDoseCallback =
+                ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
+        }
+    }
+
+    auto status = halSoundDose->registerSoundDoseCallback(mHalSoundDoseCallback);
+    if (!status.isOk()) {
+        // Not a warning since this can happen if the callback was registered before
+        ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
+              __func__,
+              status.getMessage());
+    }
+
+    return true;
+}
+
 void SoundDoseManager::setOutputRs2(float rs2Value) {
     ALOGV("%s", __func__);
     std::lock_guard _l(mLock);
 
     mRs2Value = rs2Value;
+    if (mHalSoundDose != nullptr) {
+        // using the HAL sound dose interface
+        if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+            ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, mRs2Value);
+        }
+        return;
+    }
 
     for (auto& streamProcessor : mActiveProcessors) {
         sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
@@ -89,6 +145,103 @@
     }
 }
 
+audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
+    std::lock_guard _l(mLock);
+
+    audio_devices_t type;
+    std::string address;
+    auto result = aidl::android::aidl2legacy_AudioDevice_audio_device(
+            audioDevice, &type, &address);
+    if (result != NO_ERROR) {
+        ALOGE("%s: could not convert from AudioDevice to AudioDeviceTypeAddr", __func__);
+        return AUDIO_PORT_HANDLE_NONE;
+    }
+
+    auto adt = AudioDeviceTypeAddr(type, address);
+    auto deviceIt = mActiveDevices.find(adt);
+    if (deviceIt == mActiveDevices.end()) {
+        ALOGE("%s: could not find port id for device %s", __func__, adt.toString().c_str());
+        return AUDIO_PORT_HANDLE_NONE;
+    }
+    return deviceIt->second;
+}
+
+void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+                                            const audio_port_handle_t deviceId) {
+    std::lock_guard _l(mLock);
+    ALOGI("%s: map address: %s to device id: %d", __func__, adt.toString().c_str(), deviceId);
+    mActiveDevices[adt] = deviceId;
+}
+
+void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
+    std::lock_guard _l(mLock);
+    for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
+        if (activeDevice->second == deviceId) {
+            ALOGI("%s: clear mapping addr: %s to deviceId: %d",
+                  __func__, activeDevice->first.toString().c_str(), deviceId);
+            activeDevice = mActiveDevices.erase(activeDevice);
+            continue;
+        }
+        ++activeDevice;
+    }
+    return;
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
+        float in_currentDbA, const AudioDevice& in_audioDevice) {
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager == nullptr) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    std::shared_ptr<ISoundDose> halSoundDose;
+    soundDoseManager->getHalSoundDose(&halSoundDose);
+    if(halSoundDose == nullptr) {
+        ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+    if (id == AUDIO_PORT_HANDLE_NONE) {
+        ALOGW("%s: no mapped id for audio device with type %d and address %s",
+                __func__, in_audioDevice.type.type,
+                in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    soundDoseManager->onMomentaryExposure(in_currentDbA, id);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
+        const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+        const AudioDevice& in_audioDevice) {
+    auto soundDoseManager = mSoundDoseManager.promote();
+    if (soundDoseManager == nullptr) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    std::shared_ptr<ISoundDose> halSoundDose;
+    soundDoseManager->getHalSoundDose(&halSoundDose);
+    if(halSoundDose == nullptr) {
+        ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+
+    auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+    if (id == AUDIO_PORT_HANDLE_NONE) {
+        ALOGW("%s: no mapped id for audio device with type %d and address %s",
+                __func__, in_audioDevice.type.type,
+                in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    // TODO: introduce timestamp in onNewMelValues callback
+    soundDoseManager->onNewMelValues(in_melRecord.melValues, 0,
+                                     in_melRecord.melValues.size(), id);
+
+    return ndk::ScopedAStatus::ok();
+}
+
 void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
     ALOGV("%s", __func__);
 
@@ -156,11 +309,14 @@
 }
 
 void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
+    // invalidate any HAL sound dose interface used
+    setHalSoundDoseInterface(nullptr);
+
     std::lock_guard _l(mLock);
     mUseFrameworkMel = useFrameworkMel;
 }
 
-bool SoundDoseManager::useFrameworkMel() const {
+bool SoundDoseManager::forceUseFrameworkMel() const {
     std::lock_guard _l(mLock);
     return mUseFrameworkMel;
 }
@@ -170,11 +326,16 @@
     mComputeCsdOnAllDevices = computeCsdOnAllDevices;
 }
 
-bool SoundDoseManager::computeCsdOnAllDevices() const {
+bool SoundDoseManager::forceComputeCsdOnAllDevices() const {
     std::lock_guard _l(mLock);
     return mComputeCsdOnAllDevices;
 }
 
+void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
+    std::lock_guard _l(mLock);
+    *halSoundDose = mHalSoundDose;
+}
+
 void SoundDoseManager::resetSoundDose() {
     std::lock_guard lock(mLock);
     mSoundDose = nullptr;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index eb5fa49..b10874f 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -17,8 +17,11 @@
 
 #pragma once
 
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
 #include <android/media/BnSoundDose.h>
 #include <android/media/ISoundDoseCallback.h>
+#include <media/AudioDeviceTypeAddr.h>
 #include <audio_utils/MelAggregator.h>
 #include <audio_utils/MelProcessor.h>
 #include <binder/Status.h>
@@ -27,8 +30,10 @@
 
 namespace android {
 
+using aidl::android::hardware::audio::core::ISoundDose;
+
 class SoundDoseManager : public audio_utils::MelProcessor::MelCallback {
-  public:
+public:
     /** CSD is computed with a rolling window of 7 days. */
     static constexpr int64_t kCsdWindowSeconds = 604800;  // 60s * 60m * 24h * 7d
     /** Default RS2 value in dBA as defined in IEC 62368-1 3rd edition. */
@@ -36,13 +41,13 @@
 
     SoundDoseManager()
         : mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
-          mRs2Value(kDefaultRs2Value){};
+          mRs2Value(kDefaultRs2Value) {};
 
     /**
      * \brief Creates or gets the MelProcessor assigned to the streamHandle
      *
      * \param deviceId          id for the devices where the stream is active.
-     * \param streanHandle      handle to the stream
+     * \param streamHandle      handle to the stream
      * \param sampleRate        sample rate for the processor
      * \param channelCount      number of channels to be processed.
      * \param format            format of the input samples.
@@ -58,7 +63,7 @@
     /**
      * \brief Removes stream processor when MEL computation is not needed anymore
      *
-     * \param streanHandle      handle to the stream
+     * \param streamHandle      handle to the stream
      */
     void removeStreamProcessor(audio_io_handle_t streamHandle);
 
@@ -78,13 +83,31 @@
      **/
     sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
+    /**
+     * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
+     * for using the internal MEL computation.
+     *
+     * @return true if setting the HAL sound dose value was successful, false otherwise.
+     */
+    bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+
+    /** Returns the cached audio port id from the active devices. */
+    audio_port_handle_t getIdForAudioDevice(
+            const aidl::android::media::audio::common::AudioDevice& audioDevice) const;
+
+    /** Caches mapping between address and device port id. */
+    void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+                              const audio_port_handle_t deviceId);
+
+    /** Clear all map entries with passed audio_port_handle_t. */
+    void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
+
     std::string dump() const;
 
-    // used for testing
+    // used for testing only
     size_t getCachedMelRecordsSize() const;
-    bool useFrameworkMel() const;
-    bool computeCsdOnAllDevices() const;
-
+    bool forceUseFrameworkMel() const;
+    bool forceComputeCsdOnAllDevices() const;
 
     /** Method for converting from audio_utils::CsdRecord to media::SoundDoseRecord. */
     static media::SoundDoseRecord csdRecordToSoundDoseRecord(const audio_utils::CsdRecord& legacy);
@@ -101,7 +124,7 @@
     public:
         SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback)
             : mSoundDoseManager(manager),
-              mSoundDoseCallback(callback) {};
+              mSoundDoseCallback(callback) {}
 
         /** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
         virtual void binderDied(const wp<IBinder>& who);
@@ -119,6 +142,21 @@
         const sp<media::ISoundDoseCallback> mSoundDoseCallback;
     };
 
+    class HalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
+    public:
+        explicit HalSoundDoseCallback(SoundDoseManager* manager)
+            : mSoundDoseManager(manager) {}
+
+        ndk::ScopedAStatus onMomentaryExposureWarning(
+                float in_currentDbA,
+                const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+        ndk::ScopedAStatus onNewMelValues(
+                const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+                const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+
+        wp<SoundDoseManager> mSoundDoseManager;
+    };
+
     void resetSoundDose();
 
     void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records);
@@ -127,6 +165,8 @@
 
     void setUseFrameworkMel(bool useFrameworkMel);
     void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
+    /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
+    void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
 
     mutable std::mutex mLock;
 
@@ -136,12 +176,18 @@
     std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors
             GUARDED_BY(mLock);
 
+    // map active device address and type to device id
+    std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock);
+
     float mRs2Value GUARDED_BY(mLock);
 
     sp<SoundDose> mSoundDose GUARDED_BY(mLock);
 
-    bool mUseFrameworkMel GUARDED_BY(mLock);
-    bool mComputeCsdOnAllDevices GUARDED_BY(mLock);
+    std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+    std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
+
+    bool mUseFrameworkMel GUARDED_BY(mLock) = false;
+    bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
 };
 
 }  // namespace android
diff --git a/services/audioflinger/sounddose/tests/Android.bp b/services/audioflinger/sounddose/tests/Android.bp
index a886663..fef73dc 100644
--- a/services/audioflinger/sounddose/tests/Android.bp
+++ b/services/audioflinger/sounddose/tests/Android.bp
@@ -14,15 +14,24 @@
         "sounddosemanager_tests.cpp"
     ],
 
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+        "latest_android_hardware_audio_core_sounddose_ndk_static",
+        "latest_android_hardware_audio_sounddose_ndk_static",
+    ],
+
     shared_libs: [
         "audioflinger-aidl-cpp",
+        "libaudiofoundation",
         "libaudioutils",
         "libbase",
+        "libbinder_ndk",
         "liblog",
         "libutils",
     ],
 
     static_libs: [
+        "libaudio_aidl_conversion_common_ndk",
         "libgmock",
         "libsounddose",
     ],
@@ -37,4 +46,8 @@
         "-Werror",
         "-Wextra",
     ],
+
+    test_suites: [
+        "general-tests",
+    ],
 }
\ No newline at end of file
diff --git a/services/audioflinger/sounddose/tests/TEST_MAPPING b/services/audioflinger/sounddose/tests/TEST_MAPPING
new file mode 100644
index 0000000..dd7fe4d
--- /dev/null
+++ b/services/audioflinger/sounddose/tests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "sounddosemanager_tests"
+    }
+  ]
+}
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 0aa5a20..ba2edcf 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -15,25 +15,55 @@
  */
 
 // #define LOG_NDEBUG 0
-#define LOG_TAG "sounddosemanager_tests"
+#define LOG_TAG "SoundDoseManager_tests"
+
+#include <aidl/android/hardware/audio/core/BnSoundDose.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
 
 #include <SoundDoseManager.h>
 
-#include <gtest/gtest.h>
-
 namespace android {
 namespace {
 
-TEST(SoundDoseManagerTest, GetProcessorForExistingStream) {
-    SoundDoseManager soundDoseManager;
+using aidl::android::hardware::audio::core::BnSoundDose;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
+class HalSoundDoseMock : public BnSoundDose {
+public:
+    MOCK_METHOD(ndk::ScopedAStatus, getOutputRs2, (float*), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, setOutputRs2, (float), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, registerSoundDoseCallback,
+                (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>&), (override));
+};
+
+class SoundDoseManagerTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        mSoundDoseManager = sp<SoundDoseManager>::make();
+        mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+
+        ON_CALL(*mHalSoundDose.get(), setOutputRs2)
+            .WillByDefault([] (float rs2) {
+                EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+                return ndk::ScopedAStatus::ok();
+            });
+    }
+
+    sp<SoundDoseManager> mSoundDoseManager;
+    std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+};
+
+TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
     sp<audio_utils::MelProcessor> processor1 =
-        soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+        mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
             /*streamHandle=*/1,
             /*sampleRate*/44100,
             /*channelCount*/2,
             /*format*/AUDIO_FORMAT_PCM_FLOAT);
     sp<audio_utils::MelProcessor> processor2 =
-        soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+        mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
             /*streamHandle=*/1,
             /*sampleRate*/44100,
             /*channelCount*/2,
@@ -42,18 +72,17 @@
     EXPECT_EQ(processor1, processor2);
 }
 
-TEST(SoundDoseManagerTest, RemoveExistingStream) {
-    SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, RemoveExistingStream) {
     sp<audio_utils::MelProcessor> processor1 =
-        soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+        mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
             /*streamHandle=*/1,
             /*sampleRate*/44100,
             /*channelCount*/2,
             /*format*/AUDIO_FORMAT_PCM_FLOAT);
 
-    soundDoseManager.removeStreamProcessor(1);
+    mSoundDoseManager->removeStreamProcessor(1);
     sp<audio_utils::MelProcessor> processor2 =
-        soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+        mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
             /*streamHandle=*/1,
             /*sampleRate*/44100,
             /*channelCount*/2,
@@ -62,13 +91,150 @@
     EXPECT_NE(processor1, processor2);
 }
 
-TEST(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
-    SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
     std::vector<float>mels{1, 1};
 
-    soundDoseManager.onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
+    mSoundDoseManager->onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
 
-    EXPECT_EQ(soundDoseManager.getCachedMelRecordsSize(), size_t{1});
+    EXPECT_EQ(mSoundDoseManager->getCachedMelRecordsSize(), size_t{1});
+}
+
+TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
+    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
+    EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+    EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+        .Times(1)
+        .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+            EXPECT_NE(nullptr, callback);
+            return ndk::ScopedAStatus::ok();
+        });
+
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+    EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
+            /*streamHandle=*/1,
+            /*sampleRate*/44100,
+            /*channelCount*/2,
+            /*format*/AUDIO_FORMAT_PCM_FLOAT));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) {
+    EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+    EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+        .Times(1)
+        .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+            EXPECT_NE(nullptr, callback);
+            return ndk::ScopedAStatus::ok();
+        });
+
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
+    std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+    EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+    EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+       .Times(1)
+       .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+           halCallback = callback;
+           return ndk::ScopedAStatus::ok();
+       });
+
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+    EXPECT_NE(nullptr, halCallback);
+    AudioDevice audioDevice = {};
+    audioDevice.address.set<AudioDeviceAddress::id>("test");
+    auto status = halCallback->onMomentaryExposureWarning(
+        /*in_currentDbA=*/101.f, audioDevice);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturnsException) {
+    std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+    EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+    EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+       .Times(1)
+       .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+           halCallback = callback;
+           return ndk::ScopedAStatus::ok();
+       });
+
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+    EXPECT_NE(nullptr, halCallback);
+    EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+
+    AudioDevice audioDevice = {};
+    audioDevice.address.set<AudioDeviceAddress::id>("test");
+    auto status = halCallback->onMomentaryExposureWarning(
+        /*in_currentDbA=*/101.f, audioDevice);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) {
+    std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+    EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+    EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+       .Times(1)
+       .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+           halCallback = callback;
+           return ndk::ScopedAStatus::ok();
+       });
+
+    EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+    EXPECT_NE(nullptr, halCallback);
+    AudioDevice audioDevice = {};
+    audioDevice.address.set<AudioDeviceAddress::id>("test");
+    auto status = halCallback->onNewMelValues(/*in_melRecord=*/{}, audioDevice);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) {
+    const std::string address = "testAddress";
+    const audio_port_handle_t deviceId = 2;
+    const AudioDeviceTypeAddr adt{audio_devices_t{0}, address};
+    AudioDevice audioDevice;
+    audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+    mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+
+    EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) {
+    const std::string address = "testAddress";
+    const AudioDeviceTypeAddr adt {audio_devices_t{0}, address};
+    const audio_port_handle_t deviceId = 2;
+    AudioDevice audioDevice;
+    audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+    mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+    mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+
+    EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) {
+    const std::string address = "testAddress";
+    AudioDevice audioDevice;
+    audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+    EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceComputeCsdOnAllDevices) {
+    EXPECT_FALSE(mSoundDoseManager->forceComputeCsdOnAllDevices());
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
+    EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
 }
 
 }  // namespace
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 1d4eb1e..f99f76e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1280,17 +1280,26 @@
             info = getPreferredMixerAttributesInfo(
                     outputDevices.itemAt(0)->getId(),
                     mEngine->getProductStrategyForAttributes(*resultAttr));
-            if (info != nullptr && info->getUid() != uid && info->getActiveClientCount() == 0) {
-                // Only use preferred mixer when the requested uid matched or
-                // there is active client on preferred mixer.
+            // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
+            // and it is currently active.
+            if (info != nullptr && info->getUid() != uid &&
+                ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_NONE ||
+                        info->getActiveClientCount() == 0)) {
                 info = nullptr;
             }
         }
         *output = getOutputForDevices(outputDevices, session, resultAttr, config,
                 flags, isSpatialized, info, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+        // The client will be active if the client is currently preferred mixer owner and the
+        // requested configuration matches the preferred mixer configuration.
         *isBitPerfect = (info != nullptr
                 && (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
-                && *output != AUDIO_IO_HANDLE_NONE);
+                && info->getUid() == uid
+                && *output != AUDIO_IO_HANDLE_NONE
+                // When bit-perfect output is selected for the preferred mixer attributes owner,
+                // only need to consider the config matches.
+                && mOutputs.valueFor(*output)->isConfigurationMatched(
+                        clientConfig, AUDIO_OUTPUT_FLAG_NONE));
     }
     if (*output == AUDIO_IO_HANDLE_NONE) {
         AudioProfileVector profiles;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 3e4dd69..ccbbf66 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
 #include <android/media/SpatializationLevel.h>
 #include <android/media/SpatializationMode.h>
 #include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
 #include <audio_utils/SimpleLog.h>
 #include <math.h>
 #include <media/AudioEffect.h>
@@ -167,8 +168,9 @@
 
     static std::string toString(audio_latency_mode_t mode) {
         // We convert to the AIDL type to print (eventually the legacy type will be removed).
-        const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
-        return result.has_value() ? media::toString(*result) : "unknown_latency_mode";
+        const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+        return result.has_value() ?
+                media::audio::common::toString(*result) : "unknown_latency_mode";
     }
 
     /**
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7f5c7a5..3f38d01 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -161,7 +161,8 @@
             audio_port_handle_t *portId = nullptr,
             audio_attributes_t attr = {},
             audio_session_t session = AUDIO_SESSION_NONE,
-            int uid = 0);
+            int uid = 0,
+            bool* isBitPerfect = nullptr);
     void getInputForAttr(
             const audio_attributes_t &attr,
             audio_session_t session,
@@ -246,7 +247,8 @@
         audio_port_handle_t *portId,
         audio_attributes_t attr,
         audio_session_t session,
-        int uid) {
+        int uid,
+        bool* isBitPerfect) {
     audio_io_handle_t localOutput;
     if (!output) output = &localOutput;
     *output = AUDIO_IO_HANDLE_NONE;
@@ -260,14 +262,15 @@
     *portId = AUDIO_PORT_HANDLE_NONE;
     AudioPolicyInterface::output_type_t outputType;
     bool isSpatialized;
-    bool isBitPerfect;
+    bool isBitPerfectInternal;
     // TODO b/182392769: use attribution source util
     AttributionSourceState attributionSource = AttributionSourceState();
     attributionSource.uid = uid;
     attributionSource.token = sp<BBinder>::make();
     ASSERT_EQ(OK, mManager->getOutputForAttr(
                     &attr, output, session, &stream, attributionSource, &config, &flags,
-                    selectedDeviceId, portId, {}, &outputType, &isSpatialized, &isBitPerfect));
+                    selectedDeviceId, portId, {}, &outputType, &isSpatialized,
+                    isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect));
     ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
     ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
 }
@@ -1119,6 +1122,116 @@
                                                            "", "", AUDIO_FORMAT_LDAC));
 }
 
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, BitPerfectPlayback) {
+    const audio_format_t bitPerfectFormat = AUDIO_FORMAT_PCM_16_BIT;
+    const audio_channel_mask_t bitPerfectChannelMask = AUDIO_CHANNEL_OUT_QUAD;
+    const uint32_t bitPerfectSampleRate = 48000;
+    mClient->addSupportedFormat(bitPerfectFormat);
+    mClient->addSupportedChannelMask(bitPerfectChannelMask);
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+                                                           AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                                           "", "", AUDIO_FORMAT_DEFAULT));
+    auto devices = mManager->getAvailableOutputDevices();
+    audio_port_handle_t usbPortId = AUDIO_PORT_HANDLE_NONE;
+    for (auto device : devices) {
+        if (device->type() == AUDIO_DEVICE_OUT_USB_DEVICE) {
+            usbPortId = device->getId();
+            break;
+        }
+    }
+    EXPECT_NE(AUDIO_PORT_HANDLE_NONE, usbPortId);
+
+    const uid_t uid = 1234;
+    const uid_t anotherUid = 5678;
+    const audio_attributes_t mediaAttr = {
+            .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+            .usage = AUDIO_USAGE_MEDIA,
+    };
+
+    std::vector<audio_mixer_attributes_t> mixerAttributes;
+    EXPECT_EQ(NO_ERROR, mManager->getSupportedMixerAttributes(usbPortId, mixerAttributes));
+    EXPECT_GT(mixerAttributes.size(), 0);
+    size_t bitPerfectIndex = 0;
+    for (; bitPerfectIndex < mixerAttributes.size(); ++bitPerfectIndex) {
+        if (mixerAttributes[bitPerfectIndex].mixer_behavior == AUDIO_MIXER_BEHAVIOR_BIT_PERFECT) {
+            break;
+        }
+    }
+    EXPECT_LT(bitPerfectIndex, mixerAttributes.size());
+    EXPECT_EQ(bitPerfectFormat, mixerAttributes[bitPerfectIndex].config.format);
+    EXPECT_EQ(bitPerfectChannelMask, mixerAttributes[bitPerfectIndex].config.channel_mask);
+    EXPECT_EQ(bitPerfectSampleRate, mixerAttributes[bitPerfectIndex].config.sample_rate);
+    EXPECT_EQ(NO_ERROR,
+              mManager->setPreferredMixerAttributes(
+                      &mediaAttr, usbPortId, uid, &mixerAttributes[bitPerfectIndex]));
+
+    audio_io_handle_t bitPerfectOutput = AUDIO_IO_HANDLE_NONE;
+    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    audio_port_handle_t bitPerfectPortId = AUDIO_PORT_HANDLE_NONE;
+    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+    bool isBitPerfect;
+
+    // When there is no active bit-perfect playback, the output selection will follow default
+    // routing strategy.
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+            uid, &isBitPerfect);
+    EXPECT_FALSE(isBitPerfect);
+    EXPECT_NE(AUDIO_IO_HANDLE_NONE, output);
+    const auto outputDesc = mManager->getOutputs().valueFor(output);
+    EXPECT_NE(nullptr, outputDesc);
+    EXPECT_NE(AUDIO_OUTPUT_FLAG_BIT_PERFECT, outputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+    // Start bit-perfect playback
+    getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+            bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+            mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+    status_t status = mManager->startOutput(bitPerfectPortId);
+    if (status == DEAD_OBJECT) {
+        getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+                bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+                mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+        status = mManager->startOutput(bitPerfectPortId);
+    }
+    EXPECT_EQ(NO_ERROR, status);
+    EXPECT_TRUE(isBitPerfect);
+    EXPECT_NE(AUDIO_IO_HANDLE_NONE, bitPerfectOutput);
+    const auto bitPerfectOutputDesc = mManager->getOutputs().valueFor(bitPerfectOutput);
+    EXPECT_NE(nullptr, bitPerfectOutputDesc);
+    EXPECT_EQ(AUDIO_OUTPUT_FLAG_BIT_PERFECT,
+              bitPerfectOutputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+    // If the playback is from preferred mixer attributes owner but the request doesn't match
+    // preferred mixer attributes, it will not be bit-perfect.
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+            uid, &isBitPerfect);
+    EXPECT_FALSE(isBitPerfect);
+    EXPECT_EQ(bitPerfectOutput, output);
+
+    // When bit-perfect playback is active, all other playback will be routed to bit-perfect output.
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+            anotherUid, &isBitPerfect);
+    EXPECT_FALSE(isBitPerfect);
+    EXPECT_EQ(bitPerfectOutput, output);
+
+    // When configuration matches preferred mixer attributes, which is bit-perfect, but the client
+    // is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
+    getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+            bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr,
+            AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+    EXPECT_FALSE(isBitPerfect);
+    EXPECT_EQ(bitPerfectOutput, output);
+
+    EXPECT_EQ(NO_ERROR,
+              mManager->clearPreferredMixerAttributes(&mediaAttr, usbPortId, uid));
+    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+                                                           AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                                           "", "", AUDIO_FORMAT_LDAC));
+}
+
 class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
 protected:
     void TearDown() override;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index c937d3a..2eb771d 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -54,7 +54,7 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </mixPort>
-                <mixPort name="hifi_output" role="source"/>
+                <mixPort name="hifi_output" role="source" flags="AUDIO_OUTPUT_FLAG_BIT_PERFECT"/>
             </mixPorts>
             <devicePorts>
                 <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1e6524f..7b1759e 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -95,6 +95,12 @@
         "hidl/HidlCameraDeviceUser.cpp",
         "hidl/HidlCameraService.cpp",
         "hidl/Utils.cpp",
+        "aidl/AidlCameraDeviceCallbacks.cpp",
+        "aidl/AidlCameraDeviceUser.cpp",
+        "aidl/AidlCameraService.cpp",
+        "aidl/AidlCameraServiceListener.cpp",
+        "aidl/AidlUtils.cpp",
+        "aidl/DeathPipe.cpp",
         "utils/CameraServiceProxyWrapper.cpp",
         "utils/CameraThreadState.cpp",
         "utils/CameraTraces.cpp",
@@ -151,6 +157,9 @@
         "android.frameworks.cameraservice.service@2.2",
         "android.frameworks.cameraservice.device@2.0",
         "android.frameworks.cameraservice.device@2.1",
+        "android.frameworks.cameraservice.common-V1-ndk",
+        "android.frameworks.cameraservice.service-V1-ndk",
+        "android.frameworks.cameraservice.device-V1-ndk",
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 0213623..caa1750 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -33,6 +33,7 @@
 #include <android/hardware/ICamera.h>
 #include <android/hardware/ICameraClient.h>
 
+#include <aidl/AidlCameraService.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
@@ -88,6 +89,7 @@
 using binder::Status;
 using namespace camera3;
 using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
+using frameworks::cameraservice::service::implementation::AidlCameraService;
 using hardware::ICamera;
 using hardware::ICameraClient;
 using hardware::ICameraServiceListener;
@@ -196,6 +198,10 @@
               __FUNCTION__);
     }
 
+    if (!AidlCameraService::registerService(this)) {
+        ALOGE("%s: Failed to register default AIDL VNDK CameraService", __FUNCTION__);
+    }
+
     // This needs to be last call in this function, so that it's as close to
     // ServiceManager::addService() as possible.
     mCameraServiceProxyWrapper->pingCameraServiceProxy();
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
new file mode 100644
index 0000000..4c6d6f6
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraDeviceCallbacks"
+
+#include <aidl/AidlCameraDeviceCallbacks.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <hidl/Utils.h>
+#include <utility>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCaptureResultExtras =
+        ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using SPhysicalCaptureResultInfo =
+        ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+// NDK classes
+using UCaptureResultExtras = ::android::hardware::camera2::impl::CaptureResultExtras;
+using UPhysicalCaptureResultInfo = ::android::hardware::camera2::impl::PhysicalCaptureResultInfo;
+
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
+
+const char *AidlCameraDeviceCallbacks::kResultKey = "CaptureResult";
+
+
+bool AidlCameraDeviceCallbacks::initializeLooper(int vndkVersion) {
+    mCbLooper = new ALooper;
+    mCbLooper->setName("cs-looper");
+    status_t err = mCbLooper->start(/*runOnCallingThread*/ false, /*canCallJava*/ false,
+                                    PRIORITY_DEFAULT);
+    if (err !=OK) {
+        ALOGE("Unable to start camera device callback looper");
+        return false;
+    }
+    mHandler = new CallbackHandler(this, vndkVersion);
+    mCbLooper->registerHandler(mHandler);
+    return true;
+}
+
+AidlCameraDeviceCallbacks::AidlCameraDeviceCallbacks(
+        const std::shared_ptr<SICameraDeviceCallback>& base):
+      mBase(base), mDeathPipe(this, base->asBinder()) {}
+
+AidlCameraDeviceCallbacks::~AidlCameraDeviceCallbacks() {
+    if (mCbLooper != nullptr) {
+        if (mHandler != nullptr) {
+            mCbLooper->unregisterHandler(mHandler->id());
+        }
+        mCbLooper->stop();
+    }
+    mCbLooper.clear();
+    mHandler.clear();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onDeviceError(
+    int32_t errorCode, const CaptureResultExtras& resultExtras) {
+    using hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+    SCaptureResultExtras cre = convertToAidl(resultExtras);
+    auto ret = mBase->onDeviceError(convertToAidl(errorCode), cre);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceError")
+    return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onDeviceIdle() {
+    auto ret = mBase->onDeviceIdle();
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceIdle")
+    return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onCaptureStarted(
+        const CaptureResultExtras& resultExtras, int64_t timestamp) {
+    using hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+    SCaptureResultExtras hCaptureResultExtras = convertToAidl(resultExtras);
+    auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onCaptureStarted")
+    return binder::Status::ok();
+}
+
+void AidlCameraDeviceCallbacks::convertResultMetadataToAidl(const camera_metadata_t* src,
+                                                            SCaptureMetadataInfo* dst) {
+    // First try writing to fmq.
+    size_t metadata_size = get_camera_metadata_size(src);
+    if ((metadata_size > 0) &&
+        (mCaptureResultMetadataQueue->availableToWrite() > 0)) {
+        if (mCaptureResultMetadataQueue->write((int8_t *)src, metadata_size)) {
+            dst->set<SCaptureMetadataInfo::fmqMetadataSize>(metadata_size);
+        } else {
+            ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+            SCameraMetadata metadata;
+            hardware::cameraservice::utils::conversion::aidl::cloneToAidl(src, &metadata);
+            dst->set<SCaptureMetadataInfo::metadata>(std::move(metadata));
+        }
+    }
+}
+
+void AidlCameraDeviceCallbacks::CallbackHandler::onMessageReceived(const sp<AMessage> &msg) {
+    sp<RefBase> obj = nullptr;
+    sp<ResultWrapper> resultWrapper = nullptr;
+    bool found = false;
+    switch (msg->what()) {
+        case kWhatResultReceived:
+            found = msg->findObject(kResultKey, &obj);
+            if (!found || obj == nullptr) {
+                ALOGE("Cannot find result object in callback message");
+                return;
+            }
+            resultWrapper = static_cast<ResultWrapper*>(obj.get());
+            processResultMessage(resultWrapper);
+            break;
+        default:
+            ALOGE("Unknown callback sent");
+            break;
+    }
+    }
+
+void AidlCameraDeviceCallbacks::CallbackHandler::processResultMessage(
+    sp<ResultWrapper> &resultWrapper) {
+    sp<AidlCameraDeviceCallbacks> converter = mConverter.promote();
+    if (converter == nullptr) {
+        ALOGE("Callback wrapper has died, result callback cannot be made");
+        return;
+    }
+    CameraMetadataNative &result = resultWrapper->mResult;
+    auto resultExtras = resultWrapper->mResultExtras;
+    SCaptureResultExtras convResultExtras =
+            hardware::cameraservice::utils::conversion::aidl::convertToAidl(resultExtras);
+
+    // Convert Metadata into HCameraMetadata;
+    SCaptureMetadataInfo captureMetadataInfo;
+    if (filterVndkKeys(mVndkVersion, result, /*isStatic*/false) != OK) {
+        ALOGE("%s: filtering vndk keys from result failed, not sending onResultReceived callback",
+                __FUNCTION__);
+        return;
+    }
+    const camera_metadata_t *rawMetadata = result.getAndLock();
+    converter->convertResultMetadataToAidl(rawMetadata, &captureMetadataInfo);
+    result.unlock(rawMetadata);
+
+    auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
+    std::vector<SPhysicalCaptureResultInfo> stableCaptureResInfo =
+            convertToAidl(physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
+    auto ret = converter->mBase->onResultReceived(captureMetadataInfo,
+                                                  convResultExtras,
+                                                  stableCaptureResInfo);
+
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "OnResultReceived")
+}
+
+binder::Status AidlCameraDeviceCallbacks::onResultReceived(
+    const CameraMetadataNative& result,
+    const UCaptureResultExtras& resultExtras,
+    const ::std::vector<UPhysicalCaptureResultInfo>& physicalCaptureResultInfos) {
+    // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on
+    // sp<RefBase>-able structure and post it.
+    sp<ResultWrapper> resultWrapper = new ResultWrapper(const_cast<CameraMetadataNative &>(result),
+                                                        resultExtras, physicalCaptureResultInfos);
+    sp<AMessage> msg = new AMessage(kWhatResultReceived, mHandler);
+    msg->setObject(kResultKey, resultWrapper);
+    msg->post();
+    return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onPrepared(int32_t) {
+    // not implemented
+    return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onRepeatingRequestError(
+    int64_t lastFrameNumber,
+    int32_t repeatingRequestId) {
+    auto ret =
+        mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onRepeatingRequestError")
+    return binder::Status::ok();
+}
+binder::Status AidlCameraDeviceCallbacks::onRequestQueueEmpty() {
+    // not implemented
+    return binder::Status::ok();
+}
+
+status_t AidlCameraDeviceCallbacks::linkToDeath(const sp<DeathRecipient>& recipient,
+                                                void* cookie, uint32_t flags) {
+    return mDeathPipe.linkToDeath(recipient, cookie, flags);
+}
+status_t AidlCameraDeviceCallbacks::unlinkToDeath(const wp<DeathRecipient>& recipient,
+                                                  void* cookie,
+                                                  uint32_t flags,
+                                                  wp<DeathRecipient>* outRecipient) {
+    return mDeathPipe.unlinkToDeath(recipient, cookie, flags, outRecipient);
+}
+
+} // namespace android::frameworks::cameraservice::device::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
new file mode 100644
index 0000000..5cff5b3
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
+
+#include <CameraService.h>
+#include <aidl/DeathPipe.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceCallback.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <mutex>
+#include <thread>
+#include <utility>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using SICameraDeviceCallback =
+        ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+// NDK classes
+using UBnCameraDeviceCallbacks = ::android::hardware::camera2::BnCameraDeviceCallbacks;
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::frameworks::cameraservice::utils::DeathPipe;
+using ::android::hardware::camera2::impl::CameraMetadataNative;
+
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+class AidlCameraDeviceCallbacks : public UBnCameraDeviceCallbacks {
+  public:
+    explicit AidlCameraDeviceCallbacks(const std::shared_ptr<SICameraDeviceCallback>& base);
+
+    ~AidlCameraDeviceCallbacks() override;
+
+    bool initializeLooper(int vndkVersion);
+
+    binder::Status onDeviceError(int32_t errorCode,
+                                 const CaptureResultExtras& resultExtras) override;
+
+    binder::Status onDeviceIdle() override;
+
+    binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras,
+                                    int64_t timestamp) override;
+
+    binder::Status onResultReceived(
+            const CameraMetadataNative& result, const CaptureResultExtras& resultExtras,
+            const std::vector<PhysicalCaptureResultInfo>& physicalCaptureResultInfos) override;
+
+    binder::Status onPrepared(int32_t streamId) override;
+
+    binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
+                                           int32_t repeatingRequestId) override;
+
+    binder::Status onRequestQueueEmpty() 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,
+                           wp<DeathRecipient>* outRecipient) override;
+
+    void setCaptureResultMetadataQueue(std::shared_ptr<CaptureResultMetadataQueue> metadataQueue) {
+        mCaptureResultMetadataQueue = std::move(metadataQueue);
+    }
+
+ private:
+    // Wrapper struct so that parameters to onResultReceived callback may be
+    // sent through an AMessage.
+    struct ResultWrapper : public RefBase {
+        CameraMetadataNative mResult;
+        CaptureResultExtras mResultExtras;
+        std::vector<PhysicalCaptureResultInfo> mPhysicalCaptureResultInfos;
+
+        ResultWrapper(CameraMetadataNative &result,
+                      CaptureResultExtras  resultExtras,
+                      std::vector<PhysicalCaptureResultInfo> physicalCaptureResultInfos) :
+              // TODO: make this std::movable
+              mResult(result),
+              mResultExtras(std::move(resultExtras)),
+              mPhysicalCaptureResultInfos(std::move(physicalCaptureResultInfos)) { }
+    };
+
+    struct CallbackHandler : public AHandler {
+        public:
+            void onMessageReceived(const sp<AMessage> &msg) override;
+            CallbackHandler(AidlCameraDeviceCallbacks *converter, int vndkVersion) :
+                    mConverter(converter), mVndkVersion(vndkVersion) { }
+        private:
+            void processResultMessage(sp<ResultWrapper> &resultWrapper);
+            wp<AidlCameraDeviceCallbacks> mConverter = nullptr;
+            int mVndkVersion = -1;
+    };
+
+    void convertResultMetadataToAidl(const camera_metadata * src, SCaptureMetadataInfo * dst);
+    enum {
+        kWhatResultReceived,
+    };
+
+    static const char *kResultKey;
+
+  private:
+    std::shared_ptr<SICameraDeviceCallback> mBase;
+    std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+    sp<CallbackHandler> mHandler = nullptr;
+    sp<ALooper> mCbLooper = nullptr;
+
+    // Pipes death subscription from current NDK interface to VNDK mBase.
+    // Should consume calls to linkToDeath and unlinkToDeath.
+    DeathPipe mDeathPipe;
+};
+
+} // namespace android::frameworks::cameraservice::device::implementation
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
new file mode 100644
index 0000000..d9ec0b6
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraDeviceUser"
+
+#include "AidlCameraDeviceUser.h"
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+// NDK classes
+using UOutputConfiguration = ::android::hardware::camera2::params::OutputConfiguration;
+using USessionConfiguration = ::android::hardware::camera2::params::SessionConfiguration;
+using UStatus = ::android::binder::Status;
+using USubmitInfo = ::android::hardware::camera2::utils::SubmitInfo;
+
+using ::android::CameraMetadata;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneFromAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertFromAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::ndk::ScopedAStatus;
+
+namespace {
+constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+
+inline ScopedAStatus fromSStatus(const SStatus& s) {
+    return s == SStatus::NO_ERROR ? ScopedAStatus::ok()
+                                  : ScopedAStatus::fromServiceSpecificError(
+                                            static_cast<int32_t>(s));
+}
+inline ScopedAStatus fromUStatus(const UStatus& status) {
+    return status.isOk() ? ScopedAStatus::ok() : fromSStatus(convertToAidl(status));
+}
+} // anonymous namespace
+
+AidlCameraDeviceUser::AidlCameraDeviceUser(const sp<UICameraDeviceUser>& deviceRemote):
+      mDeviceRemote(deviceRemote) {
+    mInitSuccess = initDevice();
+}
+bool AidlCameraDeviceUser::initDevice() {
+    // TODO: Get request and result metadata queue size from a system property.
+    int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+
+    mCaptureRequestMetadataQueue =
+        std::make_unique<CaptureRequestMetadataQueue>(static_cast<size_t>(reqFMQSize),
+                                                      false /* non blocking */);
+    if (!mCaptureRequestMetadataQueue->isValid()) {
+        ALOGE("%s: invalid request fmq", __FUNCTION__);
+        return false;
+    }
+
+    int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+    mCaptureResultMetadataQueue =
+        std::make_shared<CaptureResultMetadataQueue>(static_cast<size_t>(resFMQSize),
+                                                     false /* non blocking */);
+    if (!mCaptureResultMetadataQueue->isValid()) {
+        ALOGE("%s: invalid result fmq", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::getCaptureRequestMetadataQueue(
+        MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
+    if (mInitSuccess) {
+        *_aidl_return = mCaptureRequestMetadataQueue->dupeDesc();
+    }
+    return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::getCaptureResultMetadataQueue(
+        MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
+    if (mInitSuccess) {
+        *_aidl_return = mCaptureResultMetadataQueue->dupeDesc();
+    }
+    return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::submitRequestList(
+        const std::vector<SCaptureRequest>& in_requestList, bool in_isRepeating,
+        SSubmitInfo* _aidl_return) {
+    USubmitInfo submitInfo;
+    std::vector<UCaptureRequest> requests;
+    for (const auto& req: in_requestList) {
+        requests.emplace_back();
+        if (!convertRequestFromAidl(req, &requests.back())) {
+            ALOGE("%s: Failed to convert AIDL CaptureRequest.", __FUNCTION__);
+            return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+        }
+    }
+    UStatus ret = mDeviceRemote->submitRequestList(requests,
+                                                   in_isRepeating, &submitInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed submitRequestList to cameraservice: %s",
+              __FUNCTION__, ret.toString8().string());
+        return fromUStatus(ret);
+    }
+    mRequestId = submitInfo.mRequestId;
+    convertToAidl(submitInfo, _aidl_return);
+    return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::cancelRepeatingRequest(int64_t* _aidl_return) {
+    UStatus ret = mDeviceRemote->cancelRequest(mRequestId, _aidl_return);
+    return fromUStatus(ret);
+}
+
+ScopedAStatus AidlCameraDeviceUser::beginConfigure() {
+    UStatus ret = mDeviceRemote->beginConfigure();
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::endConfigure(SStreamConfigurationMode in_operatingMode,
+                                                      const SCameraMetadata& in_sessionParams,
+                                                      int64_t in_startTimeNs) {
+    CameraMetadata metadata;
+    if (!cloneFromAidl(in_sessionParams, &metadata)) {
+        return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+    }
+
+    std::vector<int32_t> offlineStreamIds;
+    UStatus ret = mDeviceRemote->endConfigure(convertFromAidl(in_operatingMode),
+                                              metadata, in_startTimeNs,
+                                              &offlineStreamIds);
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::createStream(
+        const SOutputConfiguration& in_outputConfiguration, int32_t* _aidl_return) {
+    UOutputConfiguration outputConfig = convertFromAidl(in_outputConfiguration);
+    int32_t newStreamId;
+    UStatus ret = mDeviceRemote->createStream(outputConfig, &newStreamId);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().string());
+    }
+    *_aidl_return = newStreamId;
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::createDefaultRequest(STemplateId in_templateId,
+                                                              SCameraMetadata* _aidl_return) {
+    CameraMetadata metadata;
+    UStatus ret = mDeviceRemote->createDefaultRequest(convertFromAidl(in_templateId),
+                                                      &metadata);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().string());
+        return fromUStatus(ret);
+    }
+    const camera_metadata_t* rawMetadata = metadata.getAndLock();
+    cloneToAidl(rawMetadata, _aidl_return);
+    metadata.unlock(rawMetadata);
+    return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::waitUntilIdle() {
+    UStatus ret = mDeviceRemote->waitUntilIdle();
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::flush(int64_t* _aidl_return) {
+    UStatus ret = mDeviceRemote->flush(_aidl_return);
+    return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::updateOutputConfiguration(
+        int32_t in_streamId, const SOutputConfiguration& in_outputConfiguration) {
+    UOutputConfiguration outputConfig = convertFromAidl(in_outputConfiguration);
+    UStatus ret = mDeviceRemote->updateOutputConfiguration(in_streamId, outputConfig);
+    if (!ret.isOk()) {
+        ALOGE("%s: Failed to update output config for stream id: %d: %s",
+              __FUNCTION__, in_streamId, ret.toString8().string());
+    }
+    return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::isSessionConfigurationSupported(
+        const SSessionConfiguration& in_sessionConfiguration, bool* _aidl_return) {
+    USessionConfiguration sessionConfig = convertFromAidl(in_sessionConfiguration);
+    UStatus ret = mDeviceRemote->isSessionConfigurationSupported(sessionConfig,
+                                                                 _aidl_return);
+    return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::deleteStream(int32_t in_streamId) {
+    UStatus ret = mDeviceRemote->deleteStream(in_streamId);
+    return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::disconnect() {
+    UStatus ret = mDeviceRemote->disconnect();
+    return fromUStatus(ret);
+}
+bool AidlCameraDeviceUser::convertRequestFromAidl(
+        const SCaptureRequest& src, UCaptureRequest* dst) {
+    dst->mIsReprocess = false;
+    for (const auto& streamAndWindowId : src.streamAndWindowIds) {
+        dst->mStreamIdxList.push_back(streamAndWindowId.streamId);
+        dst->mSurfaceIdxList.push_back(streamAndWindowId.windowId);
+    }
+
+    return copyPhysicalCameraSettings(src.physicalCameraSettings,
+                                      &(dst->mPhysicalCameraSettings));
+}
+bool AidlCameraDeviceUser::copyPhysicalCameraSettings(
+        const std::vector<SPhysicalCameraSettings>& src,
+        std::vector<UCaptureRequest::PhysicalCameraSettings>* dst) {
+    bool converted = false;
+    for (auto &e : src) {
+        dst->emplace_back();
+        CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
+            dst->back();
+        physicalCameraSetting.id = e.id;
+
+        // Read the settings either from the fmq or straightaway from the
+        // request. We don't need any synchronization, since submitRequestList
+        // is guaranteed to be called serially by the client if it decides to
+        // use fmq.
+        if (e.settings.getTag() == SCaptureMetadataInfo::fmqMetadataSize) {
+            /**
+             * Get settings from the fmq.
+             */
+            SCameraMetadata settingsFmq;
+            int64_t metadataSize = e.settings.get<SCaptureMetadataInfo::fmqMetadataSize>();
+            settingsFmq.metadata.resize(metadataSize);
+            int8_t* metadataPtr = (int8_t*) settingsFmq.metadata.data();
+            bool read = mCaptureRequestMetadataQueue->read(metadataPtr,
+                                                           metadataSize);
+            if (!read) {
+                ALOGE("%s capture request settings could't be read from fmq size", __FUNCTION__);
+                converted = false;
+            } else {
+                converted = cloneFromAidl(settingsFmq, &physicalCameraSetting.settings);
+            }
+        } else {
+            /**
+             * The settings metadata is contained in request settings field.
+             */
+            converted = cloneFromAidl(e.settings.get<SCaptureMetadataInfo::metadata>(),
+                    &physicalCameraSetting.settings);
+        }
+        if (!converted) {
+          ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__);
+          return false;
+        }
+    }
+    return true;
+}
+
+} // namespace android::frameworks::cameraservice::device::implementation
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
new file mode 100644
index 0000000..41a3f43
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
+
+#include <CameraService.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/hardware/common/fmq/MQDescriptor.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <fmq/AidlMessageQueue.h>
+#include <memory>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using CaptureRequestMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+// Stable NDK classes
+using SBnCameraDeviceUser = ::aidl::android::frameworks::cameraservice::device::BnCameraDeviceUser;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCaptureRequest = ::aidl::android::frameworks::cameraservice::device::CaptureRequest;
+using SOutputConfiguration =
+        ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using SPhysicalCameraSettings =
+        ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using SSessionConfiguration =
+        ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+using SStreamConfigurationMode =
+        ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using SSubmitInfo = ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using STemplateId = ::aidl::android::frameworks::cameraservice::device::TemplateId;
+// Unstable NDK classes
+using UCaptureRequest= ::android::hardware::camera2::CaptureRequest;
+using UICameraDeviceUser = ::android::hardware::camera2::ICameraDeviceUser;
+
+static constexpr int32_t REQUEST_ID_NONE = -1;
+
+class AidlCameraDeviceUser final : public SBnCameraDeviceUser {
+  public:
+    explicit AidlCameraDeviceUser(const sp<UICameraDeviceUser> &deviceRemote);
+    ~AidlCameraDeviceUser() override = default;
+
+    ndk::ScopedAStatus beginConfigure() override;
+    ndk::ScopedAStatus cancelRepeatingRequest(int64_t* _aidl_return) override;
+    ndk::ScopedAStatus createDefaultRequest(STemplateId in_templateId,
+                                            SCameraMetadata* _aidl_return) override;
+    ndk::ScopedAStatus createStream(const SOutputConfiguration& in_outputConfiguration,
+                                    int32_t* _aidl_return) override;
+    ndk::ScopedAStatus deleteStream(int32_t in_streamId) override;
+    ndk::ScopedAStatus disconnect() override;
+    ndk::ScopedAStatus endConfigure(SStreamConfigurationMode in_operatingMode,
+                                    const SCameraMetadata& in_sessionParams,
+                                    int64_t in_startTimeNs) override;
+    ndk::ScopedAStatus flush(int64_t* _aidl_return) override;
+    ndk::ScopedAStatus getCaptureRequestMetadataQueue(
+            MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) override;
+    ndk::ScopedAStatus getCaptureResultMetadataQueue(
+            MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) override;
+    ndk::ScopedAStatus isSessionConfigurationSupported(
+            const SSessionConfiguration& in_sessionConfiguration, bool* _aidl_return) override;
+    ndk::ScopedAStatus submitRequestList(const std::vector<SCaptureRequest>& in_requestList,
+                                         bool in_isRepeating, SSubmitInfo* _aidl_return) override;
+    ndk::ScopedAStatus updateOutputConfiguration(
+            int32_t in_streamId, const SOutputConfiguration& in_outputConfiguration) override;
+    ndk::ScopedAStatus waitUntilIdle() override;
+
+    [[nodiscard]] bool initStatus() const { return mInitSuccess; }
+
+    std::shared_ptr<CaptureResultMetadataQueue> getCaptureResultMetadataQueue() {
+        return mCaptureResultMetadataQueue;
+    }
+
+  private:
+    bool initDevice();
+
+    bool convertRequestFromAidl(const SCaptureRequest &src, UCaptureRequest *dst);
+    bool copyPhysicalCameraSettings(const std::vector<SPhysicalCameraSettings> &src,
+                                    std::vector<CaptureRequest::PhysicalCameraSettings> *dst);
+
+    const sp<UICameraDeviceUser> mDeviceRemote;
+    std::unique_ptr<CaptureRequestMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
+    std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+    bool mInitSuccess = false;
+    int32_t mRequestId = REQUEST_ID_NONE;
+};
+
+} // namespace android::frameworks::cameraservice::device::implementation
+
+#endif  // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
new file mode 100644
index 0000000..4232a81
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraService"
+
+#include "AidlCameraService.h"
+#include <aidl/AidlCameraDeviceCallbacks.h>
+#include <aidl/AidlCameraDeviceUser.h>
+#include <aidl/AidlCameraServiceListener.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/CameraMetadataType.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <binder/Status.h>
+#include <hidl/HidlTransportSupport.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::frameworks::cameraservice::device::implementation::AidlCameraDeviceCallbacks;
+using ::android::frameworks::cameraservice::device::implementation::AidlCameraDeviceUser;
+using ::android::hardware::cameraservice::utils::conversion::aidl::areBindersEqual;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
+using ::ndk::ScopedAStatus;
+
+// VNDK classes
+using SCameraMetadataType = ::aidl::android::frameworks::cameraservice::common::CameraMetadataType;
+using SVendorTag = ::aidl::android::frameworks::cameraservice::common::VendorTag;
+using SVendorTagSection = ::aidl::android::frameworks::cameraservice::common::VendorTagSection;
+// NDK classes
+using UICameraService = ::android::hardware::ICameraService;
+using UStatus = ::android::binder::Status;
+
+namespace {
+inline ScopedAStatus fromSStatus(const SStatus& s) {
+    return s == SStatus::NO_ERROR ? ScopedAStatus::ok()
+                                  : ScopedAStatus::fromServiceSpecificError(
+                                            static_cast<int32_t>(s));
+}
+inline ScopedAStatus fromUStatus(const UStatus& s) {
+    return s.isOk() ? ScopedAStatus::ok() : fromSStatus(convertToAidl(s));
+}
+} // anonymous namespace
+
+std::shared_ptr<AidlCameraService> kCameraService;
+
+bool AidlCameraService::registerService(::android::CameraService* cameraService) {
+    kCameraService = SharedRefBase::make<AidlCameraService>(cameraService);
+    std::string serviceName = SBnCameraService::descriptor;
+    serviceName += "/default";
+    bool isDeclared = AServiceManager_isDeclared(serviceName.c_str());
+    if (!isDeclared) {
+        ALOGI("%s: AIDL vndk not declared.", __FUNCTION__);
+        return false;
+    }
+
+    binder_exception_t registered = AServiceManager_addService(
+            kCameraService->asBinder().get(), serviceName.c_str());
+    ALOGE_IF(registered != EX_NONE,
+             "%s: AIDL VNDK declared, but failed to register service: %d",
+             __FUNCTION__, registered);
+    return registered == EX_NONE;
+}
+
+AidlCameraService::AidlCameraService(::android::CameraService* cameraService):
+      mCameraService(cameraService) {
+    mVndkVersion = base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
+}
+ScopedAStatus AidlCameraService::getCameraCharacteristics(const std::string& in_cameraId,
+                                                          SCameraMetadata* _aidl_return) {
+    if (_aidl_return == nullptr) { return fromSStatus(SStatus::ILLEGAL_ARGUMENT); }
+
+    ::android::CameraMetadata cameraMetadata;
+    UStatus ret = mCameraService->getCameraCharacteristics(String16(in_cameraId.c_str()),
+                                                           mVndkVersion,
+                                                           /* overrideToPortrait= */ false,
+                                                           &cameraMetadata);
+    if (!ret.isOk()) {
+        if (ret.exceptionCode() != EX_SERVICE_SPECIFIC) {
+            ALOGE("%s: Transaction error when getting camera characteristics"
+                  " from camera service: %d.",
+                  __FUNCTION__ , ret.exceptionCode());
+            return fromUStatus(ret);
+        }
+        switch (ret.serviceSpecificErrorCode()) {
+            case UICameraService::ERROR_ILLEGAL_ARGUMENT:
+                ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, in_cameraId.c_str());
+                return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+            default:
+                ALOGE("Get camera characteristics from camera service failed: %s",
+                      ret.toString8().string());
+                return fromUStatus(ret);
+        }
+    }
+
+    if (filterVndkKeys(mVndkVersion, cameraMetadata) != OK) {
+         ALOGE("%s: Unable to filter vndk metadata keys for version %d",
+              __FUNCTION__, mVndkVersion);
+         return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+
+    const camera_metadata_t* rawMetadata = cameraMetadata.getAndLock();
+    cloneToAidl(rawMetadata, _aidl_return);
+    cameraMetadata.unlock(rawMetadata);
+
+    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) {
+    // Here, we first get NDK ICameraDeviceUser from mCameraService, then save
+    // that interface in the newly created AidlCameraDeviceUser impl class.
+    if (mCameraService == nullptr) {
+        return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+    sp<hardware::camera2::ICameraDeviceUser> unstableDevice = nullptr;
+    // Create a hardware::camera2::ICameraDeviceCallback object which internally
+    // calls callback functions passed through hCallback.
+    sp<AidlCameraDeviceCallbacks> hybridCallbacks = new AidlCameraDeviceCallbacks(in_callback);
+    if (!hybridCallbacks->initializeLooper(mVndkVersion)) {
+        ALOGE("Unable to handle callbacks on device, cannot connect");
+        return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+    sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
+    binder::Status serviceRet = mCameraService->connectDevice(
+            callbacks,
+            String16(in_cameraId.c_str()),
+            String16(""),
+            /* clientFeatureId= */{},
+            hardware::ICameraService::USE_CALLING_UID,
+            /* scoreOffset= */ 0,
+            /* targetSdkVersion= */ __ANDROID_API_FUTURE__,
+            /* overrideToPortrait= */ false,
+            &unstableDevice);
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: Unable to connect to camera device: %s", __FUNCTION__,
+              serviceRet.toString8().c_str());
+        return fromUStatus(serviceRet);
+    }
+
+    // Now we create a AidlCameraDeviceUser class, store the unstableDevice in it,
+    // and return that back. All calls on that interface will be forwarded to
+    // the NDK AIDL interface.
+    std::shared_ptr<AidlCameraDeviceUser> stableDevice =
+            ndk::SharedRefBase::make<AidlCameraDeviceUser>(unstableDevice);
+    if (!stableDevice->initStatus()) {
+        ALOGE("%s: Unable to initialize camera device AIDL wrapper", __FUNCTION__);
+        return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+    hybridCallbacks->setCaptureResultMetadataQueue(
+            stableDevice->getCaptureResultMetadataQueue());
+    *_aidl_return = stableDevice;
+    return ScopedAStatus::ok();
+}
+void AidlCameraService::addToListenerCacheLocked(
+        std::shared_ptr<SICameraServiceListener> stableCsListener,
+        sp<UICameraServiceListener> csListener) {
+    mListeners.emplace_back(std::make_pair(stableCsListener, csListener));
+}
+sp<UICameraServiceListener> AidlCameraService::searchListenerCacheLocked(
+        const std::shared_ptr<SICameraServiceListener>& listener, bool removeIfFound) {
+    // Go through the mListeners list and compare the listener with the VNDK AIDL
+    // listener registered.
+    if (listener == nullptr) {
+        return nullptr;
+    }
+
+    auto it = mListeners.begin();
+    sp<UICameraServiceListener> csListener = nullptr;
+    for (;it != mListeners.end(); it++) {
+        if (areBindersEqual(listener->asBinder(), it->first->asBinder())) {
+            break;
+        }
+    }
+    if (it != mListeners.end()) {
+        csListener = it->second;
+        if (removeIfFound) {
+            mListeners.erase(it);
+        }
+    }
+    return csListener;
+}
+ndk::ScopedAStatus AidlCameraService::addListener(
+        const std::shared_ptr<SICameraServiceListener>& in_listener,
+        std::vector<SCameraStatusAndId>* _aidl_return) {
+    std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+    SStatus status = addListenerInternal(
+            in_listener, &cameraStatusAndIds);
+    if (status != SStatus::NO_ERROR) {
+        return fromSStatus(status);
+    }
+
+    // Convert cameraStatusAndIds to VNDK AIDL
+    convertToAidl(cameraStatusAndIds, _aidl_return);
+    return ScopedAStatus::ok();
+}
+SStatus AidlCameraService::addListenerInternal(
+        const std::shared_ptr<SICameraServiceListener>& listener,
+        std::vector<hardware::CameraStatus>* cameraStatusAndIds) {
+    if (mCameraService == nullptr) {
+        return SStatus::UNKNOWN_ERROR;
+    }
+    if (listener == nullptr || cameraStatusAndIds == nullptr) {
+        ALOGE("%s listener and cameraStatusAndIds must not be NULL", __FUNCTION__);
+        return SStatus::ILLEGAL_ARGUMENT;
+    }
+    sp<UICameraServiceListener> csListener = nullptr;
+    // Check the cache for previously registered callbacks
+    {
+        Mutex::Autolock l(mListenerListLock);
+        csListener = searchListenerCacheLocked(listener);
+        if (csListener == nullptr) {
+            // Wrap a listener with AidlCameraServiceListener and pass it to
+            // CameraService.
+            csListener = sp<AidlCameraServiceListener>::make(listener);
+            // Add to cache
+            addToListenerCacheLocked(listener, csListener);
+        } else {
+            ALOGE("%s: Trying to add a listener %p already registered",
+                  __FUNCTION__, listener.get());
+            return SStatus::ILLEGAL_ARGUMENT;
+        }
+    }
+    binder::Status serviceRet =
+            mCameraService->addListenerHelper(csListener, cameraStatusAndIds, true);
+    if (!serviceRet.isOk()) {
+        ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
+        return convertToAidl(serviceRet);
+    }
+
+    cameraStatusAndIds->erase(std::remove_if(cameraStatusAndIds->begin(),
+                                             cameraStatusAndIds->end(),
+            [this](const hardware::CameraStatus& s) {
+                bool supportsHAL3 = false;
+                binder::Status sRet =
+                            mCameraService->supportsCameraApi(String16(s.cameraId),
+                                    UICameraService::API_VERSION_2, &supportsHAL3);
+                return !sRet.isOk() || !supportsHAL3;
+            }), cameraStatusAndIds->end());
+
+    return SStatus::NO_ERROR;
+}
+ndk::ScopedAStatus AidlCameraService::removeListener(
+        const std::shared_ptr<SICameraServiceListener>& in_listener) {
+    if (in_listener == nullptr) {
+        ALOGE("%s listener must not be NULL", __FUNCTION__);
+        return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+    }
+    sp<UICameraServiceListener> csListener = nullptr;
+    {
+        Mutex::Autolock l(mListenerListLock);
+        csListener = searchListenerCacheLocked(in_listener, /*removeIfFound*/true);
+    }
+    if (csListener != nullptr) {
+          mCameraService->removeListener(csListener);
+    } else {
+        ALOGE("%s Removing unregistered listener %p", __FUNCTION__, in_listener.get());
+        return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+    }
+    return ScopedAStatus::ok();
+}
+ndk::ScopedAStatus AidlCameraService::getCameraVendorTagSections(
+        std::vector<SProviderIdAndVendorTagSections>* _aidl_return) {
+    sp<VendorTagDescriptorCache> gCache = VendorTagDescriptorCache::getGlobalVendorTagCache();
+    if (gCache == nullptr) {
+        return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+
+    const std::unordered_map<metadata_vendor_id_t, sp<android::VendorTagDescriptor>>
+            &vendorIdsAndTagDescs = gCache->getVendorIdsAndTagDescriptors();
+    if (vendorIdsAndTagDescs.empty()) {
+        return fromSStatus(SStatus::UNKNOWN_ERROR);
+    }
+
+    std::vector<SProviderIdAndVendorTagSections>& tagIdAndVendorTagSections = *_aidl_return;
+    tagIdAndVendorTagSections.resize(vendorIdsAndTagDescs.size());
+    size_t j = 0;
+    for (auto &vendorIdAndTagDescs : vendorIdsAndTagDescs) {
+        std::vector<SVendorTagSection> vendorTagSections;
+        sp<VendorTagDescriptor> desc = vendorIdAndTagDescs.second;
+        const SortedVector<String8>* sectionNames = desc->getAllSectionNames();
+        size_t numSections = sectionNames->size();
+        std::vector<std::vector<SVendorTag>> tagsBySection(numSections);
+        int tagCount = desc->getTagCount();
+        if (tagCount <= 0) {
+            continue;
+        }
+        std::vector<uint32_t> tags(tagCount);
+        desc->getTagArray(tags.data());
+        for (int i = 0; i < tagCount; i++) {
+            SVendorTag vt;
+            vt.tagId = tags[i];
+            vt.tagName = desc->getTagName(tags[i]);
+            vt.tagType = (SCameraMetadataType) desc->getTagType(tags[i]);
+            ssize_t sectionIdx = desc->getSectionIndex(tags[i]);
+            tagsBySection[sectionIdx].push_back(vt);
+        }
+        vendorTagSections.resize(numSections);
+        for (size_t s = 0; s < numSections; s++) {
+            vendorTagSections[s].sectionName = (*sectionNames)[s].string();
+            vendorTagSections[s].tags = tagsBySection[s];
+        }
+        SProviderIdAndVendorTagSections & prvdrIdAndVendorTagSection =
+                tagIdAndVendorTagSections[j];
+        prvdrIdAndVendorTagSection.providerId = vendorIdAndTagDescs.first;
+        prvdrIdAndVendorTagSection.vendorTagSections = std::move(vendorTagSections);
+        j++;
+    }
+    return ScopedAStatus::ok();
+}
+
+} // namespace android::frameworks::cameraservice::service::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.h b/services/camera/libcameraservice/aidl/AidlCameraService.h
new file mode 100644
index 0000000..4c67ac7
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
+
+#include <CameraService.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/service/BnCameraService.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+// VNDK classes
+using SBnCameraService = ::aidl::android::frameworks::cameraservice::service::BnCameraService;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SICameraDeviceCallback =
+        ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+using SICameraDeviceUser = ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser;
+using SICameraServiceListener =
+        ::aidl::android::frameworks::cameraservice::service::ICameraServiceListener;
+using SProviderIdAndVendorTagSections =
+        ::aidl::android::frameworks::cameraservice::common::ProviderIdAndVendorTagSections;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+// NDK classes
+using UICameraServiceListener = ::android::hardware::ICameraServiceListener;
+
+class AidlCameraService: public SBnCameraService {
+  public:
+    static bool registerService(::android::CameraService* cameraService);
+
+    explicit AidlCameraService(::android::CameraService* cameraService);
+    ~AidlCameraService() override = default;
+    ndk::ScopedAStatus getCameraCharacteristics(const std::string& in_cameraId,
+                                                SCameraMetadata* _aidl_return) override;
+
+    ndk::ScopedAStatus connectDevice(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+                                     const std::string& in_cameraId,
+                                     std::shared_ptr<SICameraDeviceUser>* _aidl_return) override;
+
+    ndk::ScopedAStatus addListener(const std::shared_ptr<SICameraServiceListener>& in_listener,
+                                   std::vector<SCameraStatusAndId>* _aidl_return) override;
+
+    ndk::ScopedAStatus getCameraVendorTagSections(
+            std::vector<SProviderIdAndVendorTagSections>* _aidl_return) override;
+
+    ndk::ScopedAStatus removeListener(
+            const std::shared_ptr<SICameraServiceListener>& in_listener) override;
+
+  private:
+    void addToListenerCacheLocked(std::shared_ptr<SICameraServiceListener> stableCsListener,
+                                  sp<hardware::ICameraServiceListener> csListener);
+
+    sp<UICameraServiceListener> searchListenerCacheLocked(
+            const std::shared_ptr<SICameraServiceListener>& listener, bool removeIfFound = false);
+
+    SStatus addListenerInternal(const std::shared_ptr<SICameraServiceListener>& listener,
+                                std::vector<hardware::CameraStatus>* cameraStatusAndIds);
+
+
+    ::android::CameraService* mCameraService;
+
+    Mutex mListenerListLock;
+    std::list<std::pair<std::shared_ptr<SICameraServiceListener>,
+                        sp<UICameraServiceListener>>> mListeners;
+    int mVndkVersion = -1;
+
+};
+
+} // namespace android::frameworks::cameraservice::service::implementation
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
new file mode 100644
index 0000000..e183063
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <aidl/AidlCameraServiceListener.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertCameraStatusToAidl;
+// VNDK classes
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+
+binder::Status AidlCameraServiceListener::onStatusChanged(
+        int32_t status, const ::android::String16& cameraId) {
+    SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
+    std::string sCameraId = String8(cameraId).string();
+    auto ret = mBase->onStatusChanged(sStatus, sCameraId);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onStatusChanged")
+    return binder::Status::ok();
+}
+
+binder::Status AidlCameraServiceListener::onPhysicalCameraStatusChanged(
+        int32_t status, const ::android::String16& cameraId,
+        const ::android::String16& physicalCameraId) {
+    SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
+    std::string sCameraId = String8(cameraId).string();
+    std::string sPhysicalCameraId = String8(physicalCameraId).string();
+
+    auto ret = mBase->onPhysicalCameraStatusChanged(sStatus, sCameraId, sPhysicalCameraId);
+    LOG_STATUS_ERROR_IF_NOT_OK(ret, "onPhysicalCameraStatusChanged")
+    return binder::Status::ok();
+}
+
+::android::binder::Status AidlCameraServiceListener::onTorchStatusChanged(
+    int32_t, const ::android::String16&) {
+  // We don't implement onTorchStatusChanged
+  return binder::Status::ok();
+}
+
+::android::binder::Status AidlCameraServiceListener::onTorchStrengthLevelChanged(
+    const ::android::String16&, int32_t) {
+    // We don't implement onTorchStrengthLevelChanged
+    return binder::Status::ok();
+}
+status_t AidlCameraServiceListener::linkToDeath(const sp<DeathRecipient>& recipient, void* cookie,
+                                                uint32_t flags) {
+    return mDeathPipe.linkToDeath(recipient, cookie, flags);
+}
+status_t AidlCameraServiceListener::unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie,
+                                                  uint32_t flags,
+                                                  wp<DeathRecipient>* outRecipient) {
+    return mDeathPipe.unlinkToDeath(recipient, cookie, flags, outRecipient);
+}
+
+} // namespace android::frameworks::cameraservice::service::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
new file mode 100644
index 0000000..906dd8e
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
+
+
+#include <aidl/DeathPipe.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraServiceListener.h>
+#include <android/hardware/BnCameraServiceListener.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::frameworks::cameraservice::utils::DeathPipe;
+
+// VNDK classes
+using SCameraDeviceStatus = ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using SICameraServiceListener =
+        ::aidl::android::frameworks::cameraservice::service::ICameraServiceListener;
+// NDK classes
+using UBnCameraServiceListener = ::android::hardware::BnCameraServiceListener;
+
+/**
+ * A simple shim to pass calls from CameraService to VNDK client.
+ */
+class AidlCameraServiceListener : public UBnCameraServiceListener {
+  public:
+    AidlCameraServiceListener(const std::shared_ptr<SICameraServiceListener>& base):
+          mBase(base), mDeathPipe(this, base->asBinder()) {}
+
+    ~AidlCameraServiceListener() = default;
+
+    ::android::binder::Status onStatusChanged(int32_t status,
+            const ::android::String16& cameraId) override;
+    ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
+            const ::android::String16& cameraId,
+            const ::android::String16& physicalCameraId) override;
+
+    ::android::binder::Status onTorchStatusChanged(
+            int32_t status, const ::android::String16& cameraId) override;
+    ::android::binder::Status onTorchStrengthLevelChanged(
+            const ::android::String16& cameraId, int32_t newStrengthLevel) override;
+    binder::Status onCameraAccessPrioritiesChanged() override {
+        // TODO: no implementation yet.
+        return binder::Status::ok();
+    }
+    binder::Status onCameraOpened(const ::android::String16& /*cameraId*/,
+            const ::android::String16& /*clientPackageId*/) override {
+        // empty implementation
+        return binder::Status::ok();
+    }
+    binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) override {
+        // empty implementation
+        return binder::Status::ok();
+    }
+
+    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,
+                           wp<DeathRecipient>* outRecipient) override;
+
+  private:
+    std::shared_ptr<SICameraServiceListener> mBase;
+
+    // Pipes death subscription to current NDK AIDL interface to VNDK mBase.
+    // Should consume calls to linkToDeath and unlinkToDeath.
+    DeathPipe mDeathPipe;
+};
+
+} // android
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
new file mode 100644
index 0000000..1b8e53b
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2022 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 "AidlUtils"
+
+#include <aidl/AidlUtils.h>
+#include <aidl/VndkVersionMetadataTags.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <device3/Camera3StreamInterface.h>
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+#include <mediautils/AImageReaderUtils.h>
+
+namespace android::hardware::cameraservice::utils::conversion::aidl {
+
+using aimg::AImageReader_getHGBPFromHandle;
+using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
+
+// Note: existing data in dst will be gone. Caller still owns the memory of src
+void cloneToAidl(const camera_metadata_t* src, SCameraMetadata* dst) {
+    if (src == nullptr) {
+        ALOGW("%s:attempt to convert empty metadata to AIDL", __FUNCTION__);
+        return;
+    }
+    size_t size = get_camera_metadata_size(src);
+    uint8_t* startPtr = (uint8_t*)src;
+    uint8_t* endPtr = startPtr + size;
+    dst->metadata.assign(startPtr, endPtr);
+}
+
+// The camera metadata here is cloned. Since we're reading metadata over
+// the binder we would need to clone it in order to avoid alignment issues.
+bool cloneFromAidl(const SCameraMetadata &src, CameraMetadata *dst) {
+    const camera_metadata_t *buffer =
+            reinterpret_cast<const camera_metadata_t*>(src.metadata.data());
+    size_t expectedSize = src.metadata.size();
+    if (buffer != nullptr) {
+        int res = validate_camera_metadata_structure(buffer, &expectedSize);
+        if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+            *dst = buffer;
+        } else {
+            ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+            return false;
+        }
+    }
+    return true;
+}
+
+int32_t convertFromAidl(SStreamConfigurationMode streamConfigurationMode) {
+    switch (streamConfigurationMode) {
+        case SStreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE:
+            return camera2::ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE;
+        case SStreamConfigurationMode::NORMAL_MODE:
+            return camera2::ICameraDeviceUser::NORMAL_MODE;
+        default:
+            // TODO: Fix this
+            return camera2::ICameraDeviceUser::VENDOR_MODE_START;
+    }
+}
+
+UOutputConfiguration convertFromAidl(const SOutputConfiguration &src) {
+    std::vector<sp<IGraphicBufferProducer>> iGBPs;
+    auto &windowHandles = src.windowHandles;
+    iGBPs.reserve(windowHandles.size());
+
+    for (auto &handle : windowHandles) {
+        native_handle_t* nh = makeFromAidl(handle);
+        iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(nh)));
+        native_handle_delete(nh);
+    }
+    String16 physicalCameraId16(src.physicalCameraId.c_str());
+    UOutputConfiguration outputConfiguration(
+        iGBPs, convertFromAidl(src.rotation), physicalCameraId16,
+        src.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
+        (windowHandles.size() > 1));
+    return outputConfiguration;
+}
+
+USessionConfiguration convertFromAidl(const SSessionConfiguration &src) {
+    USessionConfiguration sessionConfig(src.inputWidth, src.inputHeight,
+                                        src.inputFormat, static_cast<int>(src.operationMode));
+
+    for (const auto& os : src.outputStreams) {
+        UOutputConfiguration config = convertFromAidl(os);
+        sessionConfig.addOutputConfiguration(config);
+    }
+
+    return sessionConfig;
+}
+
+int convertFromAidl(SOutputConfiguration::Rotation rotation) {
+    switch(rotation) {
+        case SOutputConfiguration::Rotation::R270:
+            return android::camera3::CAMERA_STREAM_ROTATION_270;
+        case SOutputConfiguration::Rotation::R180:
+            return android::camera3::CAMERA_STREAM_ROTATION_180;
+        case SOutputConfiguration::Rotation::R90:
+            return android::camera3::CAMERA_STREAM_ROTATION_90;
+        case SOutputConfiguration::Rotation::R0:
+        default:
+            return android::camera3::CAMERA_STREAM_ROTATION_0;
+    }
+}
+
+int32_t convertFromAidl(STemplateId templateId) {
+    switch(templateId) {
+        case STemplateId::PREVIEW:
+            return camera2::ICameraDeviceUser::TEMPLATE_PREVIEW;
+        case STemplateId::STILL_CAPTURE:
+            return camera2::ICameraDeviceUser::TEMPLATE_STILL_CAPTURE;
+        case STemplateId::RECORD:
+            return camera2::ICameraDeviceUser::TEMPLATE_RECORD;
+        case STemplateId::VIDEO_SNAPSHOT:
+            return camera2::ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT;
+        case STemplateId::ZERO_SHUTTER_LAG:
+            return camera2::ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG;
+        case STemplateId::MANUAL:
+            return camera2::ICameraDeviceUser::TEMPLATE_MANUAL;
+    }
+}
+
+void convertToAidl(const camera2::utils::SubmitInfo& submitInfo, SSubmitInfo* hSubmitInfo) {
+    hSubmitInfo->requestId = submitInfo.mRequestId;
+    hSubmitInfo->lastFrameNumber = submitInfo.mLastFrameNumber;
+}
+
+
+SStatus convertToAidl(const binder::Status &status) {
+    if (status.isOk()) {
+        return SStatus::NO_ERROR;
+    }
+    if (status.exceptionCode() != EX_SERVICE_SPECIFIC) {
+        return SStatus::UNKNOWN_ERROR;
+    }
+
+    switch (status.serviceSpecificErrorCode()) {
+        case hardware::ICameraService::ERROR_DISCONNECTED:
+            return SStatus::DISCONNECTED;
+        case hardware::ICameraService::ERROR_CAMERA_IN_USE:
+            return SStatus::CAMERA_IN_USE;
+        case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
+            return SStatus::MAX_CAMERAS_IN_USE;
+        case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+            return SStatus::ILLEGAL_ARGUMENT;
+        case hardware::ICameraService::ERROR_DEPRECATED_HAL:
+            // Should not reach here since we filtered legacy HALs earlier
+            return SStatus::DEPRECATED_HAL;
+        case hardware::ICameraService::ERROR_DISABLED:
+            return SStatus::DISABLED;
+        case hardware::ICameraService::ERROR_PERMISSION_DENIED:
+            return SStatus::PERMISSION_DENIED;
+        case hardware::ICameraService::ERROR_INVALID_OPERATION:
+            return SStatus::INVALID_OPERATION;
+        default:
+            return SStatus::UNKNOWN_ERROR;
+    }
+}
+
+SCaptureResultExtras convertToAidl(const UCaptureResultExtras &src) {
+    SCaptureResultExtras dst;
+    dst.requestId = src.requestId;
+    dst.burstId = src.burstId;
+    dst.frameNumber = src.frameNumber;
+    dst.partialResultCount = src.partialResultCount;
+    dst.errorStreamId = src.errorStreamId;
+    dst.errorPhysicalCameraId = String8(src.errorPhysicalCameraId).string();
+    return dst;
+}
+
+SErrorCode convertToAidl(int32_t errorCode) {
+    switch(errorCode) {
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED:
+            return SErrorCode::CAMERA_DISCONNECTED;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE :
+            return SErrorCode::CAMERA_DEVICE;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE:
+            return SErrorCode::CAMERA_SERVICE;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
+            return SErrorCode::CAMERA_REQUEST;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
+            return SErrorCode::CAMERA_RESULT;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
+            return SErrorCode::CAMERA_BUFFER;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISABLED:
+            return SErrorCode::CAMERA_DISABLED;
+        case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR:
+            return SErrorCode::CAMERA_INVALID_ERROR;
+        default:
+            return SErrorCode::CAMERA_UNKNOWN_ERROR;
+    }
+}
+
+std::vector<SPhysicalCaptureResultInfo> convertToAidl(
+        const std::vector<UPhysicalCaptureResultInfo>& src,
+        std::shared_ptr<CaptureResultMetadataQueue>& fmq) {
+    std::vector<SPhysicalCaptureResultInfo> dst;
+    dst.resize(src.size());
+    size_t i = 0;
+    for (auto &physicalCaptureResultInfo : src) {
+        dst[i++] = convertToAidl(physicalCaptureResultInfo, fmq);
+    }
+    return dst;
+}
+
+SPhysicalCaptureResultInfo convertToAidl(const UPhysicalCaptureResultInfo & src,
+                                         std::shared_ptr<CaptureResultMetadataQueue> & fmq) {
+    SPhysicalCaptureResultInfo dst;
+    dst.physicalCameraId = String8(src.mPhysicalCameraId).string();
+
+    const camera_metadata_t *rawMetadata = src.mPhysicalCameraMetadata.getAndLock();
+    // Try using fmq at first.
+    size_t metadata_size = get_camera_metadata_size(rawMetadata);
+    if ((metadata_size > 0) && (fmq->availableToWrite() > 0)) {
+        if (fmq->write((int8_t *)rawMetadata, metadata_size)) {
+            dst.physicalCameraMetadata.set<SCaptureMetadataInfo::fmqMetadataSize>(metadata_size);
+        } else {
+            ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+            SCameraMetadata metadata;
+            cloneToAidl(rawMetadata, &metadata);
+            dst.physicalCameraMetadata.set<SCaptureMetadataInfo::metadata>(std::move(metadata));
+        }
+    }
+    src.mPhysicalCameraMetadata.unlock(rawMetadata);
+    return dst;
+}
+
+void convertToAidl(const std::vector<hardware::CameraStatus> &src,
+                   std::vector<SCameraStatusAndId>* dst) {
+    dst->resize(src.size());
+    size_t i = 0;
+    for (const auto &statusAndId : src) {
+        auto &a = (*dst)[i++];
+        a.cameraId = statusAndId.cameraId.c_str();
+        a.deviceStatus = convertCameraStatusToAidl(statusAndId.status);
+        size_t numUnvailPhysicalCameras = statusAndId.unavailablePhysicalIds.size();
+        a.unavailPhysicalCameraIds.resize(numUnvailPhysicalCameras);
+        for (size_t j = 0; j < numUnvailPhysicalCameras; j++) {
+            a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j].c_str();
+        }
+    }
+}
+
+SCameraDeviceStatus convertCameraStatusToAidl(int32_t src) {
+    SCameraDeviceStatus deviceStatus = SCameraDeviceStatus::STATUS_UNKNOWN;
+    switch(src) {
+        case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
+            deviceStatus = SCameraDeviceStatus::STATUS_NOT_PRESENT;
+            break;
+        case hardware::ICameraServiceListener::STATUS_PRESENT:
+            deviceStatus = SCameraDeviceStatus::STATUS_PRESENT;
+            break;
+        case hardware::ICameraServiceListener::STATUS_ENUMERATING:
+            deviceStatus = SCameraDeviceStatus::STATUS_ENUMERATING;
+            break;
+        case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
+            deviceStatus = SCameraDeviceStatus::STATUS_NOT_AVAILABLE;
+            break;
+        default:
+            break;
+    }
+    return deviceStatus;
+}
+
+bool areBindersEqual(const ndk::SpAIBinder& b1, const ndk::SpAIBinder& b2) {
+    return !AIBinder_lt(b1.get(), b2.get()) && !AIBinder_lt(b2.get(), b1.get());
+}
+
+status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic) {
+    if (vndkVersion == __ANDROID_API_FUTURE__) {
+        // VNDK version in ro.vndk.version is a version code-name that
+        // corresponds to the current version.
+        return OK;
+    }
+    const auto &apiLevelToKeys =
+            isStatic ? static_api_level_to_keys : dynamic_api_level_to_keys;
+    // Find the vndk versions above the given vndk version. All the vndk
+    // versions above the given one, need to have their keys filtered from the
+    // metadata in order to avoid metadata invalidation.
+    auto it = apiLevelToKeys.upper_bound(vndkVersion);
+    while (it != apiLevelToKeys.end()) {
+        for (const auto &key : it->second) {
+            status_t res = metadata.erase(key);
+            if (res != OK) {
+                ALOGE("%s metadata key %d could not be erased", __FUNCTION__, key);
+                return res;
+            }
+        }
+        it++;
+    }
+    return OK;
+}
+
+} // namespace android::hardware::cameraservice::utils::conversion::aidl
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.h b/services/camera/libcameraservice/aidl/AidlUtils.h
new file mode 100644
index 0000000..c89d7ff
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlUtils.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
+
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureResultExtras.h>
+#include <aidl/android/frameworks/cameraservice/device/ErrorCode.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <android/hardware/ICameraService.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
+#include <camera/CameraMetadata.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/camera.h>
+
+namespace android::hardware::cameraservice::utils::conversion::aidl {
+
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::CameraMetadata;
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+// VNDK classes
+using SCameraDeviceStatus = ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SCaptureResultExtras =
+        ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using SErrorCode = ::aidl::android::frameworks::cameraservice::device::ErrorCode;
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using SOutputConfiguration =
+        ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using SPhysicalCaptureResultInfo =
+        ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using SSessionConfiguration =
+        ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+using SStreamConfigurationMode =
+        ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using SSubmitInfo = ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using STemplateId = ::aidl::android::frameworks::cameraservice::device::TemplateId;
+// NDK classes
+using UCaptureResultExtras = ::android::hardware::camera2::impl::CaptureResultExtras;
+using UOutputConfiguration = ::android::hardware::camera2::params::OutputConfiguration;
+using UPhysicalCaptureResultInfo = ::android::hardware::camera2::impl::PhysicalCaptureResultInfo;
+using USessionConfiguration = ::android::hardware::camera2::params::SessionConfiguration;
+
+// Common macro to log errors returned from stable AIDL calls
+#define LOG_STATUS_ERROR_IF_NOT_OK(status, callName)                                        \
+    if (!(status).isOk()) {                                                                 \
+        if ((status).getExceptionCode() == EX_SERVICE_SPECIFIC) {                           \
+            SStatus errStatus = static_cast<SStatus>((status).getServiceSpecificError());   \
+            ALOGE("%s: %s callback failed: %s", __FUNCTION__, callName,                     \
+                  toString(errStatus).c_str());                                             \
+        } else {                                                                            \
+            ALOGE("%s: Transaction failed during %s: %d", __FUNCTION__, callName,           \
+                  (status).getExceptionCode());                                             \
+        }                                                                                   \
+    }
+
+// Note: existing data in dst will be gone. Caller still owns the memory of src
+void cloneToAidl(const camera_metadata_t *src, SCameraMetadata* dst);
+
+bool cloneFromAidl(const SCameraMetadata &src, CameraMetadata *dst);
+
+int32_t convertFromAidl(SStreamConfigurationMode streamConfigurationMode);
+
+UOutputConfiguration convertFromAidl(const SOutputConfiguration &src);
+
+USessionConfiguration convertFromAidl(const SSessionConfiguration &src);
+
+int convertFromAidl(SOutputConfiguration::Rotation rotation);
+
+int32_t convertFromAidl(STemplateId templateId);
+
+void convertToAidl(const hardware::camera2::utils::SubmitInfo &submitInfo,
+                   SSubmitInfo *hSubmitInfo);
+
+SStatus convertToAidl(const binder::Status &status);
+
+SCaptureResultExtras convertToAidl(const UCaptureResultExtras &captureResultExtras);
+
+SErrorCode convertToAidl(int32_t errorCode);
+
+std::vector<SPhysicalCaptureResultInfo> convertToAidl(
+        const std::vector<UPhysicalCaptureResultInfo>& src,
+        std::shared_ptr<CaptureResultMetadataQueue>& fmq);
+
+SPhysicalCaptureResultInfo convertToAidl(const UPhysicalCaptureResultInfo& src,
+                                         std::shared_ptr<CaptureResultMetadataQueue>& fmq);
+
+void convertToAidl(const std::vector<hardware::CameraStatus> &src,
+                   std::vector<SCameraStatusAndId>* dst);
+
+SCameraDeviceStatus convertCameraStatusToAidl(int32_t src);
+
+bool areBindersEqual(const ndk::SpAIBinder& b1, const ndk::SpAIBinder& b2);
+
+status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic = true);
+
+} // namespace android::hardware::cameraservice::utils::conversion::aidl
+
+#endif  // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
diff --git a/services/camera/libcameraservice/aidl/DeathPipe.cpp b/services/camera/libcameraservice/aidl/DeathPipe.cpp
new file mode 100644
index 0000000..de46411
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/DeathPipe.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 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 "DeathPipe"
+
+#include "DeathPipe.h"
+
+namespace android::frameworks::cameraservice::utils {
+
+DeathPipe::DeathPipe(IBinder* parent, const ::ndk::SpAIBinder& binder):
+      mParent(parent), mAIBinder(binder) {
+    mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
+            AIBinder_DeathRecipient_new(DeathPipe::onDeathCallback));
+    // Set an unlinked callback that allows Obituaries to be deallocated
+    AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
+                                          DeathPipe::onUnlinkedCallback);
+}
+
+status_t DeathPipe::linkToDeath(const sp<IBinder::DeathRecipient>& recipient,
+                                void* cookie, uint32_t flags) {
+    LOG_ALWAYS_FATAL_IF(recipient == nullptr, "%s: recipient must be non-nullptr", __FUNCTION__);
+    std::lock_guard<std::mutex> _l(mLock);
+
+    // Create and immortalize an obituary before linking it to death.
+    // The created Obituary can now only be garbage collected if it is unlinked from death
+    std::shared_ptr<Obituary> obituary = std::make_shared<Obituary>(recipient, cookie,
+                                                                    flags, /* who= */ mParent);
+    obituary->immortalize();
+
+    // Ensure that "cookie" is a pointer to an immortal obituary.
+    // AIBinder_linkToDeath calls DeathPipe::onUnlinkedCallback if linking to death fails, marking
+    // it for garbage collection
+    binder_status_t ret = AIBinder_linkToDeath(mAIBinder.get(),
+                                               mDeathRecipient.get(),
+                                               /* cookie= */ obituary.get());
+    if (ret != STATUS_OK) {
+        return DEAD_OBJECT;
+    }
+    mObituaries.emplace_back(obituary);
+    return NO_ERROR;
+}
+
+status_t DeathPipe::unlinkToDeath(const wp<IBinder::DeathRecipient>& recipient,
+                                  void* cookie, uint32_t flags,
+                                  wp<IBinder::DeathRecipient>* outRecipient) {
+    std::lock_guard<std::mutex> _l(mLock);
+    // Temporary Obituary for checking equality
+    std::shared_ptr<Obituary> inObituary = std::make_shared<Obituary>(recipient, cookie,
+                                                                      flags, mParent);
+    for (auto it = mObituaries.begin(); it != mObituaries.end(); it++) {
+        if ((*inObituary) == (**it)) {
+            if (outRecipient != nullptr) {
+                *outRecipient = (*it)->recipient;
+            }
+            // Unlink the found Obituary from death. AIBinder_unlinkToDeath calls
+            // DeathPipe::onUnlinkedCallback with the given cookie when unlinking is done
+            binder_status_t ret = AIBinder_unlinkToDeath(mAIBinder.get(),
+                                                         mDeathRecipient.get(),
+                                                         /* cookie= */ (*it).get());
+            mObituaries.erase(it);
+            return ret == STATUS_OK ? NO_ERROR : DEAD_OBJECT;
+        }
+    }
+    return NAME_NOT_FOUND;
+}
+
+DeathPipe::~DeathPipe() = default;
+
+
+void DeathPipe::onDeathCallback(void* cookie) {
+    // Cookie will always be a pointer to a valid immortal Obituary
+    Obituary* obituary = static_cast<Obituary*>(cookie);
+    obituary->onDeath();
+    // Don't call Obituary::clear() because VNDK Binder will call DeathPipe::onUnlinkedCallback()
+    // when it is ready
+}
+
+void DeathPipe::onUnlinkedCallback(void* cookie) {
+    // Cookie will always be a pointer to a valid immortal Obituary.
+    Obituary* obituary = static_cast<Obituary*>(cookie);
+    // Mark obituary to be garbage collected if needed. onDeathCallback won't be called with
+    // this particular cookie after this.
+    obituary->clear();
+}
+
+} // namespace android::frameworks::cameraservice::utils
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/DeathPipe.h b/services/camera/libcameraservice/aidl/DeathPipe.h
new file mode 100644
index 0000000..a816dd0
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/DeathPipe.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <binder/Parcel.h>
+#include <list>
+
+namespace android::frameworks::cameraservice::utils {
+
+/**
+ * This is a helper class to pipe death notifications from  VNDK {@code AIBinder} to
+ * S/NDK {@code IBinder}.
+ *
+ * To use this class, create a DeathPipe member object as a field of NDK interface
+ * implementation, and forward functions {@code BBinder::linkToDeath} and
+ * {@code BBinder::unlinkToDeath} to corresponding DeathPipe functions.
+ */
+class DeathPipe {
+  public:
+    /**
+     * @param parent the NDK Binder object. Assumed to live longer than the DeathPipe
+     *               object
+     * @param binder the VNDK Binder object which DeathPipe with subscribe to.
+     */
+    explicit DeathPipe(IBinder* parent, const ::ndk::SpAIBinder& binder);
+    ~DeathPipe();
+
+    status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient, void* cookie,
+                         uint32_t flags);
+    status_t unlinkToDeath(const wp<IBinder::DeathRecipient>& recipient,
+                           void* cookie, uint32_t flags, wp<IBinder::DeathRecipient>* outRecipient);
+
+    // Static functions that will be called by VNDK binder upon death or unlinking
+    static void onDeathCallback(void* cookie);
+    static void onUnlinkedCallback(void* cookie);
+
+  private:
+    /**
+     * {@code Obituary} is a tiny container that contains some metadata to pass VNDK binder's
+     * death notification to the NDK binder. A pointer to the Obituary is used as the
+     * {@code cookie} in VNDK binder's death notification.
+     *
+     * Theoretically, the VNDK binder might send out death notification after the DeathPipe
+     * object is destroyed, so care must be taken to ensure that Obituaries aren't accidentally
+     * destroyed before VNDK binder stops using its cookies.
+     *
+     */
+    struct Obituary: public std::enable_shared_from_this<Obituary> {
+        wp<IBinder::DeathRecipient> recipient; // NDK death recipient
+        void *cookie; // cookie sent by the NDK recipient
+        uint32_t flags; // flags sent by the NDK recipient
+        wp<IBinder> who; // NDK binder whose death 'recipient' subscribed to
+
+        // Self ptr to ensure we don't destroy this obituary while it can still be notified by the
+        // VNDK Binder. When populated with Obituary::immortalize, this Obituary won't be
+        // garbage collected until Obituary::clear is called.
+        std::shared_ptr<Obituary> mSelfPtr;
+
+        Obituary(const wp<IBinder::DeathRecipient>& recipient, void* cookie,
+                 uint32_t flags, IBinder* who) :
+              recipient(recipient), cookie(cookie), flags(flags),
+              who(who), mSelfPtr(nullptr) {}
+
+        // Function to be called when the VNDK Binder dies. Pipes the notification to the relevant
+        // NDK recipient if it still exists
+        void onDeath() const {
+                sp<IBinder::DeathRecipient> r = recipient.promote();
+                if (r == nullptr) { return; }
+                r->binderDied(who);
+        };
+
+        // Should be called before calling AIBinder_linkToDeath. Once this function returns this
+        // Obituary won't be garbage collected until Obituary::clear is called.
+        void immortalize() {
+            mSelfPtr = shared_from_this();
+        }
+
+        // Should be called when this Obituary can be garbage collected.
+        // Typically, after the Obituary is no longer linked to a VNDK DeathRecipient
+        void clear() {
+            mSelfPtr = nullptr;
+        }
+
+        bool operator==(const Obituary& rhs) const {
+            return recipient == rhs.recipient &&
+                   cookie == rhs.cookie &&
+                   flags == rhs.flags &&
+                   who == rhs.who;
+        }
+    };
+
+    // Parent to which the cameraservice wants to subscribe to for death notification
+    IBinder* mParent;
+
+    // VNDK Binder object to which the death notification will be bound to. If it dies,
+    // cameraservice will be notified as if mParent died.
+    ::ndk::SpAIBinder mAIBinder;
+
+    // Owning VNDK's deathRecipient ensures that all linked death notifications are cleaned up
+    // when this class destructs.
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+    // Lock to protect access to fields below.
+    std::mutex mLock;
+    // List of all obituaries created by DeathPipe, used to unlink death subscription
+    std::list<std::shared_ptr<Obituary>> mObituaries;
+
+};
+
+} // namespace android::frameworks::cameraservice::utils
+
+#endif  // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
diff --git a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
similarity index 98%
rename from services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
rename to services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index 9098fe8..48c804d 100644
--- a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -21,7 +21,7 @@
  * ! Do not edit this file directly !
  *
  * Generated automatically from vndk_camera_metadata_tags.mako. To be included in libcameraservice
- * only by hidl/Utils.cpp.
+ * only by aidl/AidlUtils.cpp.
  */
 
 /**
@@ -108,5 +108,6 @@
           ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
           ANDROID_EXTENSION_CURRENT_TYPE,
           ANDROID_EXTENSION_STRENGTH,
+          ANDROID_SCALER_RAW_CROP_REGION,
         }  },
 };
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
index 3392db1..de51ffa 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
@@ -17,6 +17,7 @@
 
 #include <hidl/AidlCameraDeviceCallbacks.h>
 #include <hidl/Utils.h>
+#include <aidl/AidlUtils.h>
 
 namespace android {
 namespace frameworks {
@@ -144,7 +145,7 @@
 
     // Convert Metadata into HCameraMetadata;
     FmqSizeOrMetadata hResult;
-    using hardware::cameraservice::utils::conversion::filterVndkKeys;
+    using hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
     if (filterVndkKeys(mVndkVersion, result, /*isStatic*/false) != OK) {
         ALOGE("%s: filtering vndk keys from result failed, not sending onResultReceived callback",
                 __FUNCTION__);
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 259e8a5..1d5213d 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -21,6 +21,7 @@
 #include <hidl/HidlCameraService.h>
 #include <hidl/HidlCameraDeviceUser.h>
 #include <hidl/Utils.h>
+#include <aidl/AidlUtils.h>
 
 #include <hidl/HidlTransportSupport.h>
 
@@ -34,9 +35,9 @@
 using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
 using hardware::hidl_vec;
 using hardware::cameraservice::utils::conversion::convertToHidl;
-using hardware::cameraservice::utils::conversion::filterVndkKeys;
 using hardware::cameraservice::utils::conversion::B2HStatus;
 using hardware::Void;
+using hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
 
 using device::V2_0::implementation::H2BCameraDeviceCallbacks;
 using device::V2_1::implementation::HidlCameraDeviceUser;
diff --git a/services/camera/libcameraservice/hidl/Utils.cpp b/services/camera/libcameraservice/hidl/Utils.cpp
index 057a6e9..2a24a23 100644
--- a/services/camera/libcameraservice/hidl/Utils.cpp
+++ b/services/camera/libcameraservice/hidl/Utils.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <hidl/Utils.h>
-#include <hidl/VndkVersionMetadataTags.h>
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
 #include <cutils/native_handle.h>
 #include <mediautils/AImageReaderUtils.h>
@@ -298,31 +297,6 @@
     return hPhysicalCaptureResultInfos;
 }
 
-status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic) {
-    if (vndkVersion == __ANDROID_API_FUTURE__) {
-        // VNDK version in ro.vndk.version is a version code-name that
-        // corresponds to the current version.
-        return OK;
-    }
-    const auto &apiLevelToKeys =
-            isStatic ? static_api_level_to_keys : dynamic_api_level_to_keys;
-    // Find the vndk versions above the given vndk version. All the vndk
-    // versions above the given one, need to have their keys filtered from the
-    // metadata in order to avoid metadata invalidation.
-    auto it = apiLevelToKeys.upper_bound(vndkVersion);
-    while (it != apiLevelToKeys.end()) {
-        for (const auto &key : it->second) {
-            status_t res = metadata.erase(key);
-            if (res != OK) {
-                ALOGE("%s metadata key %d could not be erased", __FUNCTION__, key);
-                return res;
-            }
-        }
-        it++;
-    }
-    return OK;
-}
-
 } //conversion
 } // utils
 } //cameraservice
diff --git a/services/camera/libcameraservice/hidl/Utils.h b/services/camera/libcameraservice/hidl/Utils.h
index e6d4393..ec06571 100644
--- a/services/camera/libcameraservice/hidl/Utils.h
+++ b/services/camera/libcameraservice/hidl/Utils.h
@@ -97,8 +97,6 @@
 
 HStatus B2HStatus(const binder::Status &bStatus);
 
-status_t filterVndkKeys(int vndk_version, CameraMetadata &metadata, bool isStatic = true);
-
 } // conversion
 } // utils
 } // cameraservice