Merge "Drm framework change based on new aidl interface cleanup"
diff --git a/apex/manifest.json b/apex/manifest.json
index 5d72031..2cf7296 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,6 +1,6 @@
 {
   "name": "com.android.media",
-  "version": 319999900,
+  "version": 339999900,
   "requireNativeLibs": [
     "libandroid.so",
     "libbinder_ndk.so",
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index b0d962d..82463a2 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,6 @@
 {
   "name": "com.android.media.swcodec",
-  "version": 319999900,
+  "version": 339999900,
   "requireNativeLibs": [
     ":sphal"
   ]
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index af3c492..3473780 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <camera/CameraUtils.h>
+#include <camera/camera2/OutputConfiguration.h>
 #include <media/hardware/HardwareAPI.h>
 
 #include <android-base/properties.h>
@@ -31,7 +32,7 @@
 const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
 
 status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
-                /*out*/int32_t* transform) {
+        int mirrorMode, /*out*/int32_t* transform) {
     ALOGV("%s", __FUNCTION__);
 
     if (transform == NULL) {
@@ -55,9 +56,18 @@
 
     int32_t& flags = *transform;
 
-    bool mirror = (entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT);
+    int32_t mirror = 0;
+    if (mirrorMode == OutputConfiguration::MIRROR_MODE_AUTO &&
+            entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+    } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_H) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+    } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_V) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_V;
+    }
+
     int orientation = entry.data.i32[0];
-    if (!mirror) {
+    if (mirror == 0) {
         switch (orientation) {
             case 0:
                 flags = 0;
@@ -77,25 +87,25 @@
                 return INVALID_OPERATION;
         }
     } else {
-        // Front camera needs to be horizontally flipped for mirror-like behavior.
+        // - Front camera needs to be horizontally flipped for mirror-like behavior.
+        // - Application-specified mirroring needs to be applied.
         // Note: Flips are applied before rotates; using XOR here as some of these flags are
         // composed in terms of other flip/rotation flags, and are not bitwise-ORable.
         switch (orientation) {
             case 0:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+                flags = mirror;
                 break;
             case 90:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_270;
                 break;
             case 180:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_180;
                 break;
             case 270:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_90;
-
                 break;
             default:
                 ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index a16e747..4300f9a 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -89,6 +89,10 @@
     return mTimestampBase;
 }
 
+int OutputConfiguration::getMirrorMode() const {
+    return mMirrorMode;
+}
+
 OutputConfiguration::OutputConfiguration() :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID),
@@ -100,7 +104,8 @@
         mIsMultiResolution(false),
         mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
         mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
-        mTimestampBase(TIMESTAMP_BASE_DEFAULT) {
+        mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+        mMirrorMode(MIRROR_MODE_AUTO) {
 }
 
 OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -199,6 +204,12 @@
         return err;
     }
 
+    int mirrorMode = MIRROR_MODE_AUTO;
+    if ((err = parcel->readInt32(&mirrorMode)) != OK) {
+        ALOGE("%s: Failed to read mirroring mode from parcel", __FUNCTION__);
+        return err;
+    }
+
     mRotation = rotation;
     mSurfaceSetID = setID;
     mSurfaceType = surfaceType;
@@ -209,6 +220,7 @@
     mIsMultiResolution = isMultiResolution != 0;
     mStreamUseCase = streamUseCase;
     mTimestampBase = timestampBase;
+    mMirrorMode = mirrorMode;
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
                 surface.graphicBufferProducer.get(),
@@ -220,9 +232,11 @@
     mDynamicRangeProfile = dynamicProfile;
 
     ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
-          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d",
+          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d,"
+          " mirrorMode = %d",
           __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType,
-          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase);
+          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase,
+          mMirrorMode);
 
     return err;
 }
@@ -240,6 +254,7 @@
     mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
     mStreamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
     mTimestampBase = TIMESTAMP_BASE_DEFAULT;
+    mMirrorMode = MIRROR_MODE_AUTO;
 }
 
 OutputConfiguration::OutputConfiguration(
@@ -251,7 +266,8 @@
     mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false),
     mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
     mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
-    mTimestampBase(TIMESTAMP_BASE_DEFAULT) { }
+    mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+    mMirrorMode(MIRROR_MODE_AUTO) { }
 
 status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
 
@@ -307,6 +323,9 @@
     err = parcel->writeInt32(mTimestampBase);
     if (err != OK) return err;
 
+    err = parcel->writeInt32(mMirrorMode);
+    if (err != OK) return err;
+
     return OK;
 }
 
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 6d884cb..22bb234 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -43,6 +43,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V1-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.4",
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index a397ccd..31d25e7 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -37,10 +37,13 @@
          * metadata.  This is based on the sensor orientation and lens facing
          * attributes of the camera device.
          *
+         * If mirrorMode is not AUTO, it will be used to override the lens
+         * facing based mirror.
+         *
          * Returns OK on success, or a negative error code.
          */
         static status_t getRotationTransform(const CameraMetadata& staticInfo,
-                /*out*/int32_t* transform);
+                int mirrorMode, /*out*/int32_t* transform);
 
         /**
          * Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 9a91cc0..d7abfba 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -38,13 +38,19 @@
         SURFACE_TYPE_SURFACE_VIEW = 0,
         SURFACE_TYPE_SURFACE_TEXTURE = 1
     };
-    enum TimestampBaseByte {
+    enum TimestampBaseType {
         TIMESTAMP_BASE_DEFAULT = 0,
         TIMESTAMP_BASE_SENSOR = 1,
         TIMESTAMP_BASE_MONOTONIC = 2,
         TIMESTAMP_BASE_REALTIME = 3,
         TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4
     };
+    enum MirrorModeType {
+        MIRROR_MODE_AUTO = 0,
+        MIRROR_MODE_NONE = 1,
+        MIRROR_MODE_H = 2,
+        MIRROR_MODE_V = 3,
+    };
 
     const std::vector<sp<IGraphicBufferProducer>>& getGraphicBufferProducers() const;
     int                        getRotation() const;
@@ -59,6 +65,7 @@
     bool                       isMultiResolution() const;
     int                        getStreamUseCase() const;
     int                        getTimestampBase() const;
+    int                        getMirrorMode() const;
 
     // set of sensor pixel mode resolutions allowed {MAX_RESOLUTION, DEFAULT_MODE};
     const std::vector<int32_t>&            getSensorPixelModesUsed() const;
@@ -103,7 +110,8 @@
                 sensorPixelModesUsedEqual(other) &&
                 mDynamicRangeProfile == other.mDynamicRangeProfile &&
                 mStreamUseCase == other.mStreamUseCase &&
-                mTimestampBase == other.mTimestampBase);
+                mTimestampBase == other.mTimestampBase &&
+                mMirrorMode == other.mMirrorMode);
     }
     bool operator != (const OutputConfiguration& other) const {
         return !(*this == other);
@@ -149,6 +157,9 @@
         if (mTimestampBase != other.mTimestampBase) {
             return mTimestampBase < other.mTimestampBase;
         }
+        if (mMirrorMode != other.mMirrorMode) {
+            return mMirrorMode < other.mMirrorMode;
+        }
         return gbpsLessThan(other);
     }
 
@@ -176,6 +187,7 @@
     int                        mDynamicRangeProfile;
     int                        mStreamUseCase;
     int                        mTimestampBase;
+    int                        mMirrorMode;
 };
 } // namespace params
 } // namespace camera2
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 2997b67..2d1f741 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -13,7 +13,6 @@
 
     srcs: [
         "CreatePluginFactories.cpp",
-        "CryptoFactory.cpp",
         "CryptoPlugin.cpp",
         "DrmFactory.cpp",
         "DrmPlugin.cpp",
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp
index 5f6bfe8..4e6fe3a 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp
@@ -25,10 +25,6 @@
   return ::ndk::SharedRefBase::make<DrmFactory>();
 }
 
-std::shared_ptr<CryptoFactory> createCryptoFactory() {
-    return ::ndk::SharedRefBase::make<CryptoFactory>();
-}
-
 }  // namespace clearkey
 }  // namespace drm
 }  // namespace hardware
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp
deleted file mode 100644
index 43b325d..0000000
--- a/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "clearkey-CryptoFactory"
-#include <utils/Log.h>
-
-#include "CryptoFactory.h"
-
-#include "ClearKeyUUID.h"
-#include "CryptoPlugin.h"
-#include "AidlUtils.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace drm {
-namespace clearkey {
-
-using ::aidl::android::hardware::drm::Status;
-using ::aidl::android::hardware::drm::Uuid;
-
-using std::vector;
-
-::ndk::ScopedAStatus CryptoFactory::createPlugin(
-        const ::aidl::android::hardware::drm::Uuid& in_uuid,
-        const std::vector<uint8_t>& in_initData,
-        std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) {
-    if (!isClearKeyUUID(in_uuid.uuid.data())) {
-        ALOGE("Clearkey Drm HAL: failed to create crypto plugin, "
-              "invalid crypto scheme");
-        *_aidl_return = nullptr;
-        return toNdkScopedAStatus(Status::BAD_VALUE);
-    }
-
-    std::shared_ptr<CryptoPlugin> plugin = ::ndk::SharedRefBase::make<CryptoPlugin>(in_initData);
-    Status status = plugin->getInitStatus();
-    if (status != Status::OK) {
-        plugin.reset();
-        plugin = nullptr;
-    }
-    *_aidl_return = plugin;
-    return toNdkScopedAStatus(status);
-}
-
-::ndk::ScopedAStatus CryptoFactory::isCryptoSchemeSupported(const Uuid& in_uuid,
-                                                            bool* _aidl_return) {
-    *_aidl_return = isClearKeyUUID(in_uuid.uuid.data());
-    return ::ndk::ScopedAStatus::ok();
-}
-
-}  // namespace clearkey
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
index b65d40f..651d8f5 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
@@ -31,110 +31,101 @@
 
 using ::aidl::android::hardware::drm::Status;
 
-::ndk::ScopedAStatus CryptoPlugin::decrypt(
-        bool in_secure, const std::vector<uint8_t>& in_keyId, const std::vector<uint8_t>& in_iv,
-        ::aidl::android::hardware::drm::Mode in_mode,
-        const ::aidl::android::hardware::drm::Pattern& in_pattern,
-        const std::vector<::aidl::android::hardware::drm::SubSample>& in_subSamples,
-        const ::aidl::android::hardware::drm::SharedBuffer& in_source, int64_t in_offset,
-        const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
-        ::aidl::android::hardware::drm::DecryptResult* _aidl_return) {
-    UNUSED(in_pattern);
+::ndk::ScopedAStatus CryptoPlugin::decrypt(const DecryptArgs& in_args, int32_t* _aidl_return) {
+    const char* detailedError = "";
 
-    std::string detailedError;
-
-    _aidl_return->bytesWritten = 0;
-    if (in_secure) {
-        _aidl_return->detailedError = "secure decryption is not supported with ClearKey";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+    *_aidl_return = 0;
+    if (in_args.secure) {
+        detailedError = "secure decryption is not supported with ClearKey";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
     std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
-    if (mSharedBufferMap.find(in_source.bufferId) == mSharedBufferMap.end()) {
-        _aidl_return->detailedError = "source decrypt buffer base not set";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+    if (mSharedBufferMap.find(in_args.source.bufferId) == mSharedBufferMap.end()) {
+        detailedError = "source decrypt buffer base not set";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
-    if (in_destination.type == BufferType::SHARED_MEMORY) {
-        const SharedBuffer& dest = in_destination.nonsecureMemory;
-        if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
-            _aidl_return->detailedError = "destination decrypt buffer base not set";
-            return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
-        }
-    } else {
-        _aidl_return->detailedError = "destination type not supported";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+    const auto NON_SECURE = DestinationBuffer::Tag::nonsecureMemory;
+    if (in_args.destination.getTag() != NON_SECURE) {
+        detailedError = "destination type not supported";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
-    auto src = mSharedBufferMap[in_source.bufferId];
+    const SharedBuffer& destBuffer = in_args.destination.get<NON_SECURE>();
+    if (mSharedBufferMap.find(destBuffer.bufferId) == mSharedBufferMap.end()) {
+        detailedError = "destination decrypt buffer base not set";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
+    }
+
+    auto src = mSharedBufferMap[in_args.source.bufferId];
     if (src->mBase == nullptr) {
-        _aidl_return->detailedError = "source is a nullptr";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+        detailedError = "source is a nullptr";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
     size_t totalSize = 0;
-    if (__builtin_add_overflow(in_source.offset, in_offset, &totalSize) ||
-        __builtin_add_overflow(totalSize, in_source.size, &totalSize) || totalSize > src->mSize) {
+    if (__builtin_add_overflow(in_args.source.offset, in_args.offset, &totalSize) ||
+        __builtin_add_overflow(totalSize, in_args.source.size, &totalSize) ||
+        totalSize > src->mSize) {
         android_errorWriteLog(0x534e4554, "176496160");
-        _aidl_return->detailedError = "invalid buffer size";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+        detailedError = "invalid buffer size";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
-    // destination.type == BufferType::SHARED_MEMORY
-    const SharedBuffer& destBuffer = in_destination.nonsecureMemory;
+    // destination type must be non-secure shared memory
     auto dest = mSharedBufferMap[destBuffer.bufferId];
     if (dest->mBase == nullptr) {
-        _aidl_return->detailedError = "destination is a nullptr";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+        detailedError = "destination is a nullptr";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 
     totalSize = 0;
     if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
         totalSize > dest->mSize) {
         android_errorWriteLog(0x534e4554, "176444622");
-        _aidl_return->detailedError = "invalid buffer size";
-        return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+        detailedError = "invalid buffer size";
+        return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
     }
 
     // Calculate the output buffer size and determine if any subsamples are
     // encrypted.
-    uint8_t* srcPtr = src->mBase + in_source.offset + in_offset;
-    uint8_t* destPtr = dest->mBase + in_destination.nonsecureMemory.offset;
+    uint8_t* srcPtr = src->mBase + in_args.source.offset + in_args.offset;
+    uint8_t* destPtr = dest->mBase + destBuffer.offset;
     size_t destSize = 0;
     size_t srcSize = 0;
     bool haveEncryptedSubsamples = false;
-    for (size_t i = 0; i < in_subSamples.size(); i++) {
-        const SubSample& subSample = in_subSamples[i];
+    for (size_t i = 0; i < in_args.subSamples.size(); i++) {
+        const SubSample& subSample = in_args.subSamples[i];
         if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize) ||
             __builtin_add_overflow(srcSize, subSample.numBytesOfClearData, &srcSize)) {
-            _aidl_return->detailedError = "subsample clear size overflow";
-            return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+            detailedError = "subsample clear size overflow";
+            return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
         }
         if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize) ||
             __builtin_add_overflow(srcSize, subSample.numBytesOfEncryptedData, &srcSize)) {
-            _aidl_return->detailedError = "subsample encrypted size overflow";
-            return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+            detailedError = "subsample encrypted size overflow";
+            return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
         }
         if (subSample.numBytesOfEncryptedData > 0) {
             haveEncryptedSubsamples = true;
         }
     }
 
-    if (destSize > destBuffer.size || srcSize > in_source.size) {
-        _aidl_return->detailedError = "subsample sum too large";
-        return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+    if (destSize > destBuffer.size || srcSize > in_args.source.size) {
+        detailedError = "subsample sum too large";
+        return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
     }
 
-    if (in_mode == Mode::UNENCRYPTED) {
+    if (in_args.mode == Mode::UNENCRYPTED) {
         if (haveEncryptedSubsamples) {
-            _aidl_return->detailedError =
-                    "Encrypted subsamples found in allegedly unencrypted data.";
-            return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+            detailedError = "Encrypted subsamples found in allegedly unencrypted data.";
+            return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
         }
 
         size_t offset = 0;
-        for (size_t i = 0; i < in_subSamples.size(); ++i) {
-            const SubSample& subSample = in_subSamples[i];
+        for (size_t i = 0; i < in_args.subSamples.size(); ++i) {
+            const SubSample& subSample = in_args.subSamples[i];
             if (subSample.numBytesOfClearData != 0) {
                 memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
                        reinterpret_cast<const uint8_t*>(srcPtr) + offset,
@@ -143,37 +134,33 @@
             }
         }
 
-        _aidl_return->bytesWritten = static_cast<ssize_t>(offset);
-        _aidl_return->detailedError = "";
+        *_aidl_return = static_cast<ssize_t>(offset);
         return toNdkScopedAStatus(Status::OK);
-    } else if (in_mode == Mode::AES_CTR) {
+    } else if (in_args.mode == Mode::AES_CTR) {
         size_t bytesDecrypted{};
         std::vector<int32_t> clearDataLengths;
         std::vector<int32_t> encryptedDataLengths;
-        for (auto ss : in_subSamples) {
+        for (auto ss : in_args.subSamples) {
             clearDataLengths.push_back(ss.numBytesOfClearData);
             encryptedDataLengths.push_back(ss.numBytesOfEncryptedData);
         }
         auto res =
-                mSession->decrypt(in_keyId.data(), in_iv.data(),
+                mSession->decrypt(in_args.keyId.data(), in_args.iv.data(),
                                   srcPtr, static_cast<uint8_t*>(destPtr),
                                   clearDataLengths, encryptedDataLengths,
                                   &bytesDecrypted);
         if (res == clearkeydrm::OK) {
-            _aidl_return->bytesWritten = static_cast<ssize_t>(bytesDecrypted);
-            _aidl_return->detailedError = "";
+            *_aidl_return = static_cast<ssize_t>(bytesDecrypted);
             return toNdkScopedAStatus(Status::OK);
         } else {
-            _aidl_return->bytesWritten = 0;
-            _aidl_return->detailedError = "Decryption Error";
-            return toNdkScopedAStatus(static_cast<Status>(res));
+            *_aidl_return = 0;
+            detailedError = "Decryption Error";
+            return toNdkScopedAStatus(static_cast<Status>(res), detailedError);
         }
     } else {
-        _aidl_return->bytesWritten = 0;
-        _aidl_return->detailedError =
-                "selected encryption mode is not supported by the ClearKey DRM \
-Plugin";
-        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+        *_aidl_return = 0;
+        detailedError = "selected encryption mode is not supported by the ClearKey DRM Plugin";
+        return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
     }
 }
 
@@ -218,24 +205,22 @@
     return toNdkScopedAStatus(status);
 }
 
-::ndk::ScopedAStatus CryptoPlugin::setSharedBufferBase(
-        const ::aidl::android::hardware::common::Ashmem& in_base, int32_t in_bufferId) {
+::ndk::ScopedAStatus CryptoPlugin::setSharedBufferBase(const SharedBuffer& in_base) {
     std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
-    mSharedBufferMap[in_bufferId] = std::make_shared<SharedBufferBase>(in_base);
+    mSharedBufferMap[in_base.bufferId] = std::make_shared<SharedBufferBase>(in_base);
     return ::ndk::ScopedAStatus::ok();
 }
 
-SharedBufferBase::SharedBufferBase(const ::aidl::android::hardware::common::Ashmem& mem)
+SharedBufferBase::SharedBufferBase(const SharedBuffer& mem)
         : mBase(nullptr),
           mSize(mem.size) {
-    if (mem.fd.get() < 0) {
+    if (mem.handle.fds.empty()) {
         return;
     }
-    auto addr = mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED,
-                     mem.fd.get(), 0);
+    auto fd = mem.handle.fds[0].get();
+    auto addr = mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (addr == MAP_FAILED) {
-        ALOGE("mmap err: fd %d; errno %s",
-              mem.fd.get(), strerror(errno));
+        ALOGE("mmap err: fd %d; errno %s", fd, strerror(errno));
     } else {
         mBase = static_cast<uint8_t*>(addr);
     }
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp
index 35c2382..bef05ec 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp
@@ -20,6 +20,7 @@
 #include "DrmFactory.h"
 
 #include "ClearKeyUUID.h"
+#include "CryptoPlugin.h"
 #include "DrmPlugin.h"
 #include "MimeTypeStdStr.h"
 #include "SessionLibrary.h"
@@ -38,7 +39,7 @@
 using ::aidl::android::hardware::drm::Status;
 using ::aidl::android::hardware::drm::Uuid;
 
-::ndk::ScopedAStatus DrmFactory::createPlugin(
+::ndk::ScopedAStatus DrmFactory::createDrmPlugin(
         const Uuid& in_uuid, const string& in_appPackageName,
         std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) {
     UNUSED(in_appPackageName);
@@ -56,42 +57,39 @@
     return toNdkScopedAStatus(Status::OK);
 }
 
-::ndk::ScopedAStatus DrmFactory::getSupportedCryptoSchemes(vector<Uuid>* _aidl_return) {
-    vector<Uuid> schemes;
-    Uuid scheme;
-    for (const auto& uuid : ::aidl::android::hardware::drm::clearkey::getSupportedCryptoSchemes()) {
-        scheme.uuid.assign(uuid.begin(), uuid.end());
-        schemes.push_back(scheme);
+::ndk::ScopedAStatus DrmFactory::createCryptoPlugin(
+        const Uuid& in_uuid, const std::vector<uint8_t>& in_initData,
+        std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) {
+    if (!isClearKeyUUID(in_uuid.uuid.data())) {
+        ALOGE("Clearkey Drm HAL: failed to create crypto plugin, "
+              "invalid crypto scheme");
+        *_aidl_return = nullptr;
+        return toNdkScopedAStatus(Status::BAD_VALUE);
     }
+
+    std::shared_ptr<CryptoPlugin> plugin = ::ndk::SharedRefBase::make<CryptoPlugin>(in_initData);
+    Status status = plugin->getInitStatus();
+    if (status != Status::OK) {
+        plugin.reset();
+        plugin = nullptr;
+    }
+    *_aidl_return = plugin;
+    return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmFactory::getSupportedCryptoSchemes(CryptoSchemes* _aidl_return) {
+    CryptoSchemes schemes{};
+    for (const auto& uuid : ::aidl::android::hardware::drm::clearkey::getSupportedCryptoSchemes()) {
+        schemes.uuids.push_back({uuid});
+    }
+    schemes.minLevel = SecurityLevel::SW_SECURE_CRYPTO;
+    schemes.maxLevel = SecurityLevel::SW_SECURE_CRYPTO;
+    schemes.mimeTypes = {kIsoBmffVideoMimeType, kIsoBmffAudioMimeType, kCencInitDataFormat,
+                         kWebmVideoMimeType, kWebmAudioMimeType, kWebmInitDataFormat};
     *_aidl_return = schemes;
     return ndk::ScopedAStatus::ok();
 }
 
-::ndk::ScopedAStatus DrmFactory::isContentTypeSupported(const string& in_mimeType,
-                                                        bool* _aidl_return) {
-    // This should match the in_mimeTypes handed by InitDataParser.
-    *_aidl_return = in_mimeType == kIsoBmffVideoMimeType || in_mimeType == kIsoBmffAudioMimeType ||
-                    in_mimeType == kCencInitDataFormat || in_mimeType == kWebmVideoMimeType ||
-                    in_mimeType == kWebmAudioMimeType || in_mimeType == kWebmInitDataFormat ||
-                    in_mimeType.empty();
-    return ::ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus DrmFactory::isCryptoSchemeSupported(const Uuid& in_uuid,
-                                                         const string& in_mimeType,
-                                                         SecurityLevel in_securityLevel,
-                                                         bool* _aidl_return) {
-    bool isSupportedMimeType = false;
-    if (!isContentTypeSupported(in_mimeType, &isSupportedMimeType).isOk()) {
-        ALOGD("%s mime type is not supported by crypto scheme", in_mimeType.c_str());
-    }
-    *_aidl_return = isClearKeyUUID(in_uuid.uuid.data()) && isSupportedMimeType &&
-                    (in_securityLevel == SecurityLevel::SW_SECURE_CRYPTO ||
-                     in_securityLevel == SecurityLevel::DEFAULT ||
-                     in_securityLevel == SecurityLevel::UNKNOWN);
-    return ::ndk::ScopedAStatus::ok();
-}
-
 binder_status_t DrmFactory::dump(int fd, const char** args, uint32_t numArgs) {
     UNUSED(args);
     UNUSED(numArgs);
@@ -111,4 +109,4 @@
 }  // namespace drm
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index 76b4667..7331ded 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -583,7 +583,7 @@
 
         std::vector<uint8_t> keyId3 = {0x0, 0x1, 0x2};
         keyStatus.keyId = keyId3;
-        keyStatus.type = KeyStatusType::USABLEINFUTURE;
+        keyStatus.type = KeyStatusType::USABLE_IN_FUTURE;
         keysStatus.push_back(keyStatus);
 
         sendKeysChange(sessionId, keysStatus, true);
@@ -764,15 +764,6 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
-::ndk::ScopedAStatus DrmPlugin::requiresSecureDecoderDefault(const std::string& in_mime,
-                                                             bool* _aidl_return) {
-    UNUSED(in_mime);
-    // Clearkey only supports SW_SECURE_CRYPTO, so we always returns false
-    // regardless of mime type.
-    *_aidl_return = false;
-    return ::ndk::ScopedAStatus::ok();
-}
-
 ::ndk::ScopedAStatus DrmPlugin::restoreKeys(
         const std::vector<uint8_t>& in_sessionId,
         const ::aidl::android::hardware::drm::KeySetId& in_keySetId) {
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Service.cpp b/drm/mediadrm/plugins/clearkey/aidl/Service.cpp
index 7d342f3..0b07864 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Service.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Service.cpp
@@ -26,9 +26,7 @@
 using ::android::base::InitLogging;
 using ::android::base::LogdLogger;
 
-using ::aidl::android::hardware::drm::clearkey::createCryptoFactory;
 using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
-using ::aidl::android::hardware::drm::clearkey::CryptoFactory;
 using ::aidl::android::hardware::drm::clearkey::DrmFactory;
 
 int main(int /*argc*/, char* argv[]) {
@@ -42,11 +40,6 @@
             AServiceManager_addService(drmFactory->asBinder().get(), drmInstance.c_str());
     CHECK(status == STATUS_OK);
 
-    std::shared_ptr<CryptoFactory> cryptoFactory = createCryptoFactory();
-    const std::string cryptoInstance = std::string() + CryptoFactory::descriptor + "/clearkey";
-    status = AServiceManager_addService(cryptoFactory->asBinder().get(), cryptoInstance.c_str());
-    CHECK(status == STATUS_OK);
-
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reached
 }
diff --git a/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp b/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp
index 55aa6e0..c3a33bb 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp
@@ -24,29 +24,20 @@
 #include <android/binder_process.h>
 
 using ::android::base::InitLogging;
-using ::android::base::StderrLogger;
+using ::android::base::LogdLogger;
 
-using ::aidl::android::hardware::drm::clearkey::createCryptoFactory;
 using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
-using ::aidl::android::hardware::drm::clearkey::CryptoFactory;
 using ::aidl::android::hardware::drm::clearkey::DrmFactory;
 
 int main(int /*argc*/, char* argv[]) {
-    InitLogging(argv, StderrLogger);
+    InitLogging(argv, LogdLogger());
     ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
     ABinderProcess_setThreadPoolMaxThreadCount(8);
 
-    binder_status_t status{};
     std::shared_ptr<DrmFactory> drmFactory = createDrmFactory();
     const std::string drmInstance = std::string() + DrmFactory::descriptor + "/clearkey";
-    status = AServiceManager_registerLazyService(drmFactory->asBinder().get(),
-                                                 drmInstance.c_str());
-    CHECK(status == STATUS_OK);
-
-    std::shared_ptr<CryptoFactory> cryptoFactory = createCryptoFactory();
-    const std::string cryptoInstance = std::string() + CryptoFactory::descriptor + "/clearkey";
-    status = AServiceManager_registerLazyService(cryptoFactory->asBinder().get(),
-                                                 cryptoInstance.c_str());
+    binder_status_t status =
+            AServiceManager_registerLazyService(drmFactory->asBinder().get(), drmInstance.c_str());
     CHECK(status == STATUS_OK);
 
     ABinderProcess_joinThreadPool();
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc
index 2b2637f..e9252cd 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc
@@ -5,4 +5,3 @@
     ioprio rt 4
     task_profiles ProcessCapacityHigh
     interface aidl android.hardware.drm.IDrmFactory/clearkey
-    interface aidl android.hardware.drm.ICryptoFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml
index 73c15f3..ac3e922 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml
@@ -2,7 +2,6 @@
     <hal format="aidl">
         <name>android.hardware.drm</name>
         <version>1</version>
-        <fqname>ICryptoFactory/clearkey</fqname>
         <fqname>IDrmFactory/clearkey</fqname>
     </hal>
 </manifest>
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
index 0370ebe..9257b17 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
@@ -40,11 +40,17 @@
     }
 }
 
-inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status) {
+inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status,
+                                               const char* msg = nullptr) {
     if (Status::OK == status) {
         return ::ndk::ScopedAStatus::ok();
     } else {
-        return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+        auto err = static_cast<int32_t>(status);
+        if (msg) {
+            return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err, msg);
+        } else {
+            return ::ndk::ScopedAStatus::fromServiceSpecificError(err);
+        }
     }
 }
 
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h
index 5a90fb8..e2afcf5 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h
@@ -15,7 +15,6 @@
  */
 #pragma once
 
-#include "CryptoFactory.h"
 #include "DrmFactory.h"
 
 namespace aidl {
@@ -23,10 +22,8 @@
 namespace hardware {
 namespace drm {
 namespace clearkey {
-//extern "C" {
+
 std::shared_ptr<DrmFactory> createDrmFactory();
-std::shared_ptr<CryptoFactory> createCryptoFactory();
-//}
 
 }  // namespace clearkey
 }  // namespace drm
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h
deleted file mode 100644
index 0d6c4ce..0000000
--- a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <aidl/android/hardware/drm/BnCryptoFactory.h>
-#include <aidl/android/hardware/drm/ICryptoFactory.h>
-#include <aidl/android/hardware/drm/ICryptoPlugin.h>
-
-#include "ClearKeyTypes.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace drm {
-namespace clearkey {
-
-struct CryptoFactory : public BnCryptoFactory {
-    CryptoFactory() {}
-    virtual ~CryptoFactory() {}
-
-    ::ndk::ScopedAStatus createPlugin(
-            const ::aidl::android::hardware::drm::Uuid& in_uuid,
-            const std::vector<uint8_t>& in_initData,
-            std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) override;
-
-    ::ndk::ScopedAStatus isCryptoSchemeSupported(
-            const ::aidl::android::hardware::drm::Uuid& in_uuid, bool* _aidl_return) override;
-
-  private:
-    CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoFactory);
-};
-
-}  // namespace clearkey
-}  // namespace drm
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h
index f98829d..60dbf77 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h
@@ -40,12 +40,13 @@
 namespace clearkey {
 
 using namespace clearkeydrm;
+using ::aidl::android::hardware::drm::DecryptArgs;
 using ::aidl::android::hardware::drm::Status;
 
 struct SharedBufferBase {
     uint8_t* mBase;
     int64_t mSize;
-    SharedBufferBase(const ::aidl::android::hardware::common::Ashmem& mem);
+    SharedBufferBase(const ::aidl::android::hardware::drm::SharedBuffer& mem);
     ~SharedBufferBase();
 };
 
@@ -59,14 +60,7 @@
     }
     virtual ~CryptoPlugin() {}
 
-    ::ndk::ScopedAStatus decrypt(
-            bool in_secure, const std::vector<uint8_t>& in_keyId, const std::vector<uint8_t>& in_iv,
-            ::aidl::android::hardware::drm::Mode in_mode,
-            const ::aidl::android::hardware::drm::Pattern& in_pattern,
-            const std::vector<::aidl::android::hardware::drm::SubSample>& in_subSamples,
-            const ::aidl::android::hardware::drm::SharedBuffer& in_source, int64_t in_offset,
-            const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
-            ::aidl::android::hardware::drm::DecryptResult* _aidl_return) override;
+    ::ndk::ScopedAStatus decrypt(const DecryptArgs& in_args, int32_t* _aidl_return) override;
 
     ::ndk::ScopedAStatus getLogMessages(
             std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) override;
@@ -79,7 +73,7 @@
     ::ndk::ScopedAStatus setMediaDrmSession(const std::vector<uint8_t>& in_sessionId) override;
 
     ::ndk::ScopedAStatus setSharedBufferBase(
-            const ::aidl::android::hardware::common::Ashmem& in_base, int32_t in_bufferId) override;
+            const ::aidl::android::hardware::drm::SharedBuffer& in_base) override;
 
     ::aidl::android::hardware::drm::Status getInitStatus() const { return mInitStatus; }
 
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h
index 0143dc7..1239aa4 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h
@@ -18,6 +18,7 @@
 #include <aidl/android/hardware/drm/BnDrmFactory.h>
 #include <aidl/android/hardware/drm/IDrmFactory.h>
 #include <aidl/android/hardware/drm/IDrmPlugin.h>
+#include <aidl/android/hardware/drm/ICryptoPlugin.h>
 
 #include <string>
 #include <vector>
@@ -34,21 +35,18 @@
     DrmFactory() {}
     virtual ~DrmFactory() {}
 
-    ::ndk::ScopedAStatus createPlugin(
+    ::ndk::ScopedAStatus createDrmPlugin(
             const ::aidl::android::hardware::drm::Uuid& in_uuid,
             const std::string& in_appPackageName,
             std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) override;
 
+    ::ndk::ScopedAStatus createCryptoPlugin(
+            const ::aidl::android::hardware::drm::Uuid& in_uuid,
+            const std::vector<uint8_t>& in_initData,
+            std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) override;
+
     ::ndk::ScopedAStatus getSupportedCryptoSchemes(
-            std::vector<::aidl::android::hardware::drm::Uuid>* _aidl_return) override;
-
-    ::ndk::ScopedAStatus isContentTypeSupported(const std::string& in_mimeType,
-                                                bool* _aidl_return) override;
-
-    ::ndk::ScopedAStatus isCryptoSchemeSupported(
-            const ::aidl::android::hardware::drm::Uuid& in_uuid, const std::string& in_mimeType,
-            ::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
-            bool* _aidl_return) override;
+            ::aidl::android::hardware::drm::CryptoSchemes* _aidl_return) override;
 
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
 
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
index 44db1d5..25c05f0 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
@@ -114,8 +114,6 @@
     ::ndk::ScopedAStatus requiresSecureDecoder(
             const std::string& in_mime, ::aidl::android::hardware::drm::SecurityLevel in_level,
             bool* _aidl_return) override;
-    ::ndk::ScopedAStatus requiresSecureDecoderDefault(const std::string& in_mime,
-                                                      bool* _aidl_return) override;
     ::ndk::ScopedAStatus restoreKeys(
             const std::vector<uint8_t>& in_sessionId,
             const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override;
diff --git a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
index 1167bb0..0233ee1 100644
--- a/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
+++ b/media/libaaudio/fuzzer/libaaudio_fuzzer.cpp
@@ -202,7 +202,7 @@
 
   int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mAaudioStream);
   uint8_t numberOfBursts = fdp.ConsumeIntegral<uint8_t>();
-  int32_t maxInputFrames = numberOfBursts * framesPerBurst;
+  int32_t maxFrames = numberOfBursts * framesPerBurst;
   int32_t requestedBufferSize =
       fdp.ConsumeIntegral<uint16_t>() * framesPerBurst;
   AAudioStream_setBufferSizeInFrames(mAaudioStream, requestedBufferSize);
@@ -218,26 +218,24 @@
 
   int32_t count = fdp.ConsumeIntegral<int32_t>();
   direction = AAudioStream_getDirection(mAaudioStream);
-  framesPerDataCallback = AAudioStream_getFramesPerDataCallback(mAaudioStream);
 
   if (actualFormat == AAUDIO_FORMAT_PCM_I16) {
-    std::vector<int16_t> inputShortData(maxInputFrames * actualChannelCount,
-                                        0x0);
-    if (direction == AAUDIO_DIRECTION_INPUT) {
-      AAudioStream_read(mAaudioStream, inputShortData.data(),
-                        framesPerDataCallback, count * kNanosPerMillisecond);
+      std::vector<int16_t> inputShortData(maxFrames * actualChannelCount, 0x0);
+      if (direction == AAUDIO_DIRECTION_INPUT) {
+          AAudioStream_read(mAaudioStream, inputShortData.data(), maxFrames,
+                            count * kNanosPerMillisecond);
     } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
-      AAudioStream_write(mAaudioStream, inputShortData.data(),
-                         framesPerDataCallback, count * kNanosPerMillisecond);
+        AAudioStream_write(mAaudioStream, inputShortData.data(), maxFrames,
+                           count * kNanosPerMillisecond);
     }
   } else if (actualFormat == AAUDIO_FORMAT_PCM_FLOAT) {
-    std::vector<float> inputFloatData(maxInputFrames * actualChannelCount, 0x0);
-    if (direction == AAUDIO_DIRECTION_INPUT) {
-      AAudioStream_read(mAaudioStream, inputFloatData.data(),
-                        framesPerDataCallback, count * kNanosPerMillisecond);
+      std::vector<float> inputFloatData(maxFrames * actualChannelCount, 0x0);
+      if (direction == AAUDIO_DIRECTION_INPUT) {
+          AAudioStream_read(mAaudioStream, inputFloatData.data(), maxFrames,
+                            count * kNanosPerMillisecond);
     } else if (direction == AAUDIO_DIRECTION_OUTPUT) {
-      AAudioStream_write(mAaudioStream, inputFloatData.data(),
-                         framesPerDataCallback, count * kNanosPerMillisecond);
+        AAudioStream_write(mAaudioStream, inputFloatData.data(), maxFrames,
+                           count * kNanosPerMillisecond);
     }
   }
 
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 40efb38..32c77c7 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1911,20 +1911,22 @@
             aps->setSurroundFormatEnabled(audioFormatAidl, enabled));
 }
 
-status_t AudioSystem::setAssistantUid(uid_t uid) {
+status_t AudioSystem::setAssistantServicesUids(const std::vector<uid_t>& uids) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
-    return statusTFromBinderStatus(aps->setAssistantUid(uidAidl));
+    std::vector<int32_t> uidsAidl = VALUE_OR_RETURN_STATUS(
+                convertContainer<std::vector<int32_t>>(uids, legacy2aidl_uid_t_int32_t));
+    return statusTFromBinderStatus(aps->setAssistantServicesUids(uidsAidl));
 }
 
-status_t AudioSystem::setHotwordDetectionServiceUid(uid_t uid) {
+status_t AudioSystem::setActiveAssistantServicesUids(const std::vector<uid_t>& activeUids) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
-    return statusTFromBinderStatus(aps->setHotwordDetectionServiceUid(uidAidl));
+    std::vector<int32_t> activeUidsAidl = VALUE_OR_RETURN_STATUS(
+                convertContainer<std::vector<int32_t>>(activeUids, legacy2aidl_uid_t_int32_t));
+    return statusTFromBinderStatus(aps->setActiveAssistantServicesUids(activeUidsAidl));
 }
 
 status_t AudioSystem::setA11yServicesUids(const std::vector<uid_t>& uids) {
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 69328a7..de0f75b 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -302,9 +302,9 @@
 
     void setSurroundFormatEnabled(in AudioFormatDescription audioFormat, boolean enabled);
 
-    void setAssistantUid(int /* uid_t */ uid);
+    void setAssistantServicesUids(in int[] /* uid_t[] */ uids);
 
-    void setHotwordDetectionServiceUid(int /* uid_t */ uid);
+    void setActiveAssistantServicesUids(in int[] /* uid_t[] */ activeUids);
 
     void setA11yServicesUids(in int[] /* uid_t[] */ uids);
 
diff --git a/media/libaudioclient/aidl/android/media/SpatializationMode.aidl b/media/libaudioclient/aidl/android/media/SpatializationMode.aidl
index 5d8fd93..eaaff37 100644
--- a/media/libaudioclient/aidl/android/media/SpatializationMode.aidl
+++ b/media/libaudioclient/aidl/android/media/SpatializationMode.aidl
@@ -24,7 +24,7 @@
 @Backing(type="byte")
 enum SpatializationMode {
     /** The spatializer supports binaural mode (over headphones type devices). */
-    SPATIALIZATER_BINAURAL = 0,
+    SPATIALIZER_BINAURAL = 0,
     /** The spatializer supports transaural mode (over speaker type devices). */
-    SPATIALIZATER_TRANSAURAL = 1,
+    SPATIALIZER_TRANSAURAL = 1,
 }
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index 4d16792..820b7cb 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -77,6 +77,26 @@
 }
 
 /**
+ * A generic template that helps convert containers of convertible types, using iterators.
+ * Uses a limit as maximum conversion items.
+ */
+template<typename InputIterator, typename OutputIterator, typename Func>
+status_t convertRangeWithLimit(InputIterator start,
+                      InputIterator end,
+                      OutputIterator out,
+                      const Func& itemConversion,
+                      const size_t limit) {
+    InputIterator last = end;
+    if (end - start > limit) {
+        last = start + limit;
+    }
+    for (InputIterator iter = start; (iter != last); ++iter, ++out) {
+        *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
+    }
+    return OK;
+}
+
+/**
  * A generic template that helps convert containers of convertible types.
  */
 template<typename OutputContainer, typename InputContainer, typename Func>
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index e0cb47e..baefee3 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -438,8 +438,9 @@
                                                audio_format_t *surroundFormats);
     static status_t setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled);
 
-    static status_t setAssistantUid(uid_t uid);
-    static status_t setHotwordDetectionServiceUid(uid_t uid);
+    static status_t setAssistantServicesUids(const std::vector<uid_t>& uids);
+    static status_t setActiveAssistantServicesUids(const std::vector<uid_t>& activeUids);
+
     static status_t setA11yServicesUids(const std::vector<uid_t>& uids);
     static status_t setCurrentImeUid(uid_t uid);
 
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index f40aa17..dd435fe 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -166,10 +166,10 @@
     ],
     shared_libs: [
         "android.hardware.audio.common@7.0",
-        "android.hardware.audio.common@7.0-util",
+        "android.hardware.audio.common@7.1-util",
         "android.hardware.audio@7.0",
         "android.hardware.audio@7.1",
-        "android.hardware.audio@7.0-util",
+        "android.hardware.audio@7.1-util",
     ],
     cflags: [
         "-DMAJOR_VERSION=7",
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 263ee67..8ba0f72 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -20,6 +20,7 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hwbinder/IPCThreadState.h>
 #include <media/AudioParameter.h>
+#include <mediautils/memory.h>
 #include <mediautils/SchedulingPolicyService.h>
 #include <utils/Log.h>
 
@@ -275,15 +276,15 @@
                                                std::optional<audio_source_t> source,
                                                audio_devices_t type) {
     LOG_ALWAYS_FATAL_IF(port.type != AUDIO_PORT_TYPE_DEVICE, "port type must be device");
-    char* address;
+    unique_malloced_ptr<char> address;
     if (strcmp(port.ext.device.address, "") != 0) {
         // FIXME: we only support address on first sink with HAL version < 3.0
-        address = audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address);
+        address.reset(
+                audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address));
     } else {
-        address = (char*)calloc(1, 1);
+        address.reset((char*)calloc(1, 1));
     }
-    AudioParameter param = AudioParameter(String8(address));
-    free(address);
+    AudioParameter param = AudioParameter(String8(address.get()));
     param.addInt(String8(AudioParameter::keyRouting), (int)type);
     if (source.has_value()) {
         param.addInt(String8(AudioParameter::keyInputSource), (int)source.value());
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index c81a659..2beb47f 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -61,7 +61,11 @@
         return true;
     }
 
-    virtual bool isValidPid(int /* pid */) {
+    virtual bool isPidTrusted(int /* pid */) {
+        return true;
+    }
+
+    virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
         return true;
     }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index c0e69d2..1ec09ea 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -256,7 +256,7 @@
             const std::shared_ptr<IResourceManagerClient> &client);
     virtual ~ResourceManagerServiceProxy();
 
-    void init();
+    status_t init();
 
     // implements DeathRecipient
     static void BinderDiedCallback(void* cookie);
@@ -285,6 +285,9 @@
         pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client)
         : mPid(pid), mUid(uid), mClient(client),
           mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
+    if (mUid == MediaCodec::kNoUid) {
+        mUid = AIBinder_getCallingUid();
+    }
     if (mPid == MediaCodec::kNoPid) {
         mPid = AIBinder_getCallingPid();
     }
@@ -303,12 +306,26 @@
     }
 }
 
-void MediaCodec::ResourceManagerServiceProxy::init() {
+status_t MediaCodec::ResourceManagerServiceProxy::init() {
     ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
     mService = IResourceManagerService::fromBinder(binder);
     if (mService == nullptr) {
         ALOGE("Failed to get ResourceManagerService");
-        return;
+        return UNKNOWN_ERROR;
+    }
+
+    int callerPid = AIBinder_getCallingPid();
+    int callerUid = AIBinder_getCallingUid();
+    if (mPid != callerPid || mUid != callerUid) {
+        // Media processes don't need special permissions to act on behalf of other processes.
+        if (callerUid != AID_MEDIA) {
+            char const * permission = "android.permission.MEDIA_RESOURCE_OVERRIDE_PID";
+            if (!checkCallingPermission(String16(permission))) {
+                ALOGW("%s is required to override the caller's PID for media resource management.",
+                        permission);
+                return PERMISSION_DENIED;
+            }
+        }
     }
 
     // Kill clients pending removal.
@@ -319,6 +336,7 @@
 
     // after this, require mLock whenever using mService
     AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+    return OK;
 }
 
 //static
@@ -801,12 +819,7 @@
       mInputBufferCounter(0),
       mGetCodecBase(getCodecBase),
       mGetCodecInfo(getCodecInfo) {
-    if (uid == kNoUid) {
-        mUid = AIBinder_getCallingUid();
-    } else {
-        mUid = uid;
-    }
-    mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
+    mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
             ::ndk::SharedRefBase::make<ResourceManagerClient>(this));
     if (!mGetCodecBase) {
         mGetCodecBase = [](const AString &name, const char *owner) {
@@ -835,7 +848,6 @@
             return NAME_NOT_FOUND;
         };
     }
-
     initMediametrics();
 }
 
@@ -1393,7 +1405,11 @@
 }
 
 status_t MediaCodec::init(const AString &name) {
-    mResourceManagerProxy->init();
+    status_t err = mResourceManagerProxy->init();
+    if (err != OK) {
+        mCodec = NULL; // remove the codec
+        return err;
+    }
 
     // save init parameters for reset
     mInitName = name;
@@ -1408,7 +1424,7 @@
     bool secureCodec = false;
     const char *owner = "";
     if (!name.startsWith("android.filter.")) {
-        status_t err = mGetCodecInfo(name, &mCodecInfo);
+        err = mGetCodecInfo(name, &mCodecInfo);
         if (err != OK) {
             mCodec = NULL;  // remove the codec.
             return err;
@@ -1481,7 +1497,6 @@
         mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this));
     }
 
-    status_t err;
     std::vector<MediaResourceParcel> resources;
     resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain)));
     for (int i = 0; i <= kMaxRetry; ++i) {
@@ -4674,7 +4689,6 @@
     mCSD.erase(mCSD.begin());
     std::shared_ptr<C2Buffer> c2Buffer;
     sp<hardware::HidlMemory> memory;
-    size_t offset = 0;
 
     if (mFlags & kFlagUseBlockModel) {
         if (hasCryptoOrDescrambler()) {
@@ -4695,7 +4709,6 @@
             memcpy(mem->unsecurePointer(), csd->data(), csd->size());
             ssize_t heapOffset;
             memory = hardware::fromHeap(mem->getMemory(&heapOffset, nullptr));
-            offset += heapOffset;
         } else {
             std::shared_ptr<C2LinearBlock> block =
                 FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 29a87e9..f5af50d 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -408,7 +408,6 @@
     struct ResourceManagerServiceProxy;
 
     State mState;
-    uid_t mUid;
     bool mReleasedByResourceManager;
     sp<ALooper> mLooper;
     sp<ALooper> mCodecLooper;
diff --git a/media/libstagefright/include/media/stagefright/ProcessInfo.h b/media/libstagefright/include/media/stagefright/ProcessInfo.h
index b8a3c10..06b9c92 100644
--- a/media/libstagefright/include/media/stagefright/ProcessInfo.h
+++ b/media/libstagefright/include/media/stagefright/ProcessInfo.h
@@ -30,7 +30,8 @@
     ProcessInfo();
 
     virtual bool getPriority(int pid, int* priority);
-    virtual bool isValidPid(int pid);
+    virtual bool isPidTrusted(int pid);
+    virtual bool isPidUidTrusted(int pid, int uid);
     virtual bool overrideProcessInfo(int pid, int procState, int oomScore);
     virtual void removeProcessInfoOverride(int pid);
 
diff --git a/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h b/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
index 9260181..b7fc858 100644
--- a/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
+++ b/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
@@ -23,7 +23,8 @@
 
 struct ProcessInfoInterface : public RefBase {
     virtual bool getPriority(int pid, int* priority) = 0;
-    virtual bool isValidPid(int pid) = 0;
+    virtual bool isPidTrusted(int pid) = 0;
+    virtual bool isPidUidTrusted(int pid, int uid) = 0;
     virtual bool overrideProcessInfo(int pid, int procState, int oomScore);
     virtual void removeProcessInfoOverride(int pid);
 
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 5a8f471..7d72510 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -558,6 +558,7 @@
                 if (n != (ssize_t)buffer->size()) {
                     ALOGW("failed to send RTCP receiver report (%s).",
                             n >= 0 ? "connection gone" : strerror(errno));
+                    ++it;
                     continue;
                 }
 
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 227459a..354971a 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -29,6 +29,7 @@
 #include <gui/Surface.h>
 
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 
 #include <media/stagefright/PersistentSurface.h>
@@ -59,6 +60,7 @@
     kWhatAsyncNotify,
     kWhatRequestActivityNotifications,
     kWhatStopActivityNotifications,
+    kWhatFrameRenderedNotify,
 };
 
 struct AMediaCodecPersistentSurface : public Surface {
@@ -98,6 +100,11 @@
     mutable Mutex mAsyncCallbackLock;
     AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
     void *mAsyncCallbackUserData;
+
+    sp<AMessage> mFrameRenderedNotify;
+    mutable Mutex mFrameRenderedCallbackLock;
+    AMediaCodecOnFrameRendered mFrameRenderedCallback;
+    void *mFrameRenderedCallbackUserData;
 };
 
 CodecHandler::CodecHandler(AMediaCodec *codec) {
@@ -294,6 +301,43 @@
             break;
         }
 
+        case kWhatFrameRenderedNotify:
+        {
+            sp<AMessage> data;
+            if (!msg->findMessage("data", &data)) {
+                ALOGE("kWhatFrameRenderedNotify: data is expected.");
+                break;
+            }
+
+            AMessage::Type type;
+            int64_t mediaTimeUs, systemNano;
+            size_t index = 0;
+
+            // TODO. This code has dependency with MediaCodec::CreateFramesRenderedMessage.
+            for (size_t ix = 0; ix < data->countEntries(); ix++) {
+                AString name = data->getEntryNameAt(ix, &type);
+                if (name.startsWith(AStringPrintf("%zu-media-time-us", index).c_str())) {
+                    AMessage::ItemData data = msg->getEntryAt(index);
+                    data.find(&mediaTimeUs);
+                } else if (name.startsWith(AStringPrintf("%zu-system-nano", index).c_str())) {
+                    AMessage::ItemData data = msg->getEntryAt(index);
+                    data.find(&systemNano);
+
+                    Mutex::Autolock _l(mCodec->mFrameRenderedCallbackLock);
+                    if (mCodec->mFrameRenderedCallback != NULL) {
+                        mCodec->mFrameRenderedCallback(
+                                mCodec,
+                                mCodec->mFrameRenderedCallbackUserData,
+                                mediaTimeUs,
+                                systemNano);
+                    }
+
+                    index++;
+                }
+            }
+            break;
+        }
+
         default:
             ALOGE("shouldn't be here");
             break;
@@ -490,6 +534,26 @@
     return AMEDIA_OK;
 }
 
+EXPORT
+media_status_t AMediaCodec_setOnFrameRenderedCallback(
+        AMediaCodec *mData,
+        AMediaCodecOnFrameRendered callback,
+        void *userdata) {
+    Mutex::Autolock _l(mData->mFrameRenderedCallbackLock);
+    if (mData->mFrameRenderedNotify == NULL) {
+        mData->mFrameRenderedNotify = new AMessage(kWhatFrameRenderedNotify, mData->mHandler);
+    }
+    status_t err = mData->mCodec->setOnFrameRenderedNotification(mData->mFrameRenderedNotify);
+    if (err != OK) {
+        ALOGE("setOnFrameRenderedNotifyCallback: err(%d), failed to set callback", err);
+        return translate_error(err);
+    }
+
+    mData->mFrameRenderedCallback = callback;
+    mData->mFrameRenderedCallbackUserData = userdata;
+
+    return AMEDIA_OK;
+}
 
 EXPORT
 media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
diff --git a/media/ndk/include/media/NdkMediaCodec.h b/media/ndk/include/media/NdkMediaCodec.h
index 519148e..5633374 100644
--- a/media/ndk/include/media/NdkMediaCodec.h
+++ b/media/ndk/include/media/NdkMediaCodec.h
@@ -39,6 +39,8 @@
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+#include <android/api-level.h>
+
 #include "NdkMediaCrypto.h"
 #include "NdkMediaError.h"
 #include "NdkMediaFormat.h"
@@ -122,6 +124,25 @@
 } AMediaCodecOnAsyncNotifyCallback;
 
 /**
+ * Called when an output frame has rendered on the output surface.
+ *
+ * \param codec       The codec object that generated this notification.
+ * \param userdata    The user data set at AMediaCodec_setOnFrameRenderedCallback.
+ * \param mediaTimeUs The presentation time (media time) of the frame rendered.
+ *                    This is usually the same as specified in
+ *                    AMediaCodec_queueInputBuffer, but some codecs may alter
+ *                    the media time by applying some time-based transformation,
+ *                    such as frame rate conversion. In that case, presentation
+ *                    time corresponds to the actual output frame rendered.
+ * \param systemNano  The system time when the frame was rendered.
+ */
+typedef void (*AMediaCodecOnFrameRendered)(
+        AMediaCodec *codec,
+        void *userdata,
+        int64_t mediaTimeUs,
+        int64_t systemNano);
+
+/**
  * Create codec by name. Use this if you know the exact codec you want to use.
  * When configuring, you will need to specify whether to use the codec as an
  * encoder or decoder.
@@ -441,6 +462,32 @@
         void *userdata) __INTRODUCED_IN(28);
 
 /**
+ * Registers a callback to be invoked when an output frame is rendered on the output surface.
+ *
+ * This method can be called in any codec state, but will only have an effect in the
+ * Executing state for codecs that render buffers to the output surface.
+ *
+ * This callback is for informational purposes only: to get precise
+ * render timing samples, and can be significantly delayed and batched. Some frames may have
+ * been rendered even if there was no callback generated.
+ *
+ * Refer to the definition of AMediaCodecOnFrameRendered on how each
+ * callback function is called and what are specified.
+ * The specified userdata is the pointer used when those callback functions are
+ * called.
+ *
+ * All callbacks are fired on one NDK internal thread.
+ * AMediaCodec_setOnFrameRenderedCallback should not be called on the callback thread.
+ * No heavy duty task should be performed on callback thread.
+ *
+ * Available since Android T.
+ */
+media_status_t AMediaCodec_setOnFrameRenderedCallback(
+        AMediaCodec*,
+        AMediaCodecOnFrameRendered callback,
+        void *userdata) __INTRODUCED_IN(__ANDROID_API_T__);
+
+/**
  * Release the crypto if applicable.
  *
  * Available since API level 28.
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index b228945..c8faced 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -203,6 +203,7 @@
     AMediaCodec_releaseOutputBuffer;
     AMediaCodec_releaseOutputBufferAtTime;
     AMediaCodec_setAsyncNotifyCallback; # introduced=28
+    AMediaCodec_setOnFrameRenderedCallback; # introduced=Tiramisu
     AMediaCodec_setOutputSurface; # introduced=24
     AMediaCodec_setParameters; # introduced=26
     AMediaCodec_setInputSurface; # introduced=26
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index c1c7df5..ba8f199 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -122,7 +122,10 @@
 
 cc_test {
     name: "libmediautils_test",
-    srcs: ["TimerThread-test.cpp"],
+    srcs: [
+        "memory-test.cpp",
+        "TimerThread-test.cpp",
+    ],
     shared_libs: [
       "libmediautils",
       "libutils",
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index e212794..da199c4 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -64,11 +64,27 @@
     return true;
 }
 
-bool ProcessInfo::isValidPid(int pid) {
+bool ProcessInfo::isPidTrusted(int pid) {
+    return isPidUidTrusted(pid, -1);
+}
+
+bool ProcessInfo::isPidUidTrusted(int pid, int uid) {
     int callingPid = IPCThreadState::self()->getCallingPid();
     int callingUid = IPCThreadState::self()->getCallingUid();
-    // Trust it if this is called from the same process otherwise pid has to match the calling pid.
-    return (callingPid == getpid()) || (callingPid == pid) || (callingUid == AID_MEDIA);
+    // Always trust when the caller is acting on their own behalf.
+    if (pid == callingPid && (uid == callingUid || uid == -1)) { // UID can be optional
+        return true;
+    }
+    // Implicitly trust when the caller is our own process.
+    if (callingPid == getpid()) {
+        return true;
+    }
+    // Implicitly trust when a media process is calling.
+    if (callingUid == AID_MEDIA) {
+        return true;
+    }
+    // Otherwise, allow the caller to act as another process when the caller has permissions.
+    return checkCallingPermission(String16("android.permission.MEDIA_RESOURCE_OVERRIDE_PID"));
 }
 
 bool ProcessInfo::overrideProcessInfo(int pid, int procState, int oomScore) {
diff --git a/media/utils/include/mediautils/memory.h b/media/utils/include/mediautils/memory.h
new file mode 100644
index 0000000..cc00bb6
--- /dev/null
+++ b/media/utils/include/mediautils/memory.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+#pragma once
+
+namespace android {
+
+namespace {
+struct FreeDeleter {
+    void operator()(void* p) { free(p); }
+};
+
+}  // namespace
+
+/**
+ * Used to wrap pointers allocated by legacy code using malloc / calloc / etc.
+ */
+template <typename T>
+using unique_malloced_ptr = std::unique_ptr<T, FreeDeleter>;
+
+}  // namespace android
diff --git a/media/utils/memory-test.cpp b/media/utils/memory-test.cpp
new file mode 100644
index 0000000..2409bc2
--- /dev/null
+++ b/media/utils/memory-test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <mediautils/memory.h>
+
+namespace android {
+namespace {
+
+TEST(UniqueMallocedPtr, Void) {
+    unique_malloced_ptr<void> p(std::malloc(10));
+}
+
+TEST(UniqueMallocedPtr, Char) {
+    unique_malloced_ptr<char> p(reinterpret_cast<char*>(std::malloc(10)));
+}
+
+TEST(UniqueMallocedPtr, Null) {
+    unique_malloced_ptr<char> p(nullptr);
+}
+
+TEST(UniqueMallocedPtr, Default) {
+    unique_malloced_ptr<char> p;
+}
+
+}  // namespace
+}  // namespace android
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index b582b3a..98a1bd9 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -108,7 +108,8 @@
     audio_attributes_t  attributes() const { return mAttr; }
 
             bool canBeSpatialized() const { return mIsOut && (mAttr.flags
-                    & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) == 0; }
+                        & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) == 0
+                    && mChannelCount > 2; }
 
 #ifdef TEE_SINK
            void         dumpTee(int fd, const std::string &reason) const {
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 582c048..4da4ea0 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -2002,34 +2002,43 @@
             mAudioPolicyManager->setSurroundFormatEnabled(audioFormat, enabled));
 }
 
-Status AudioPolicyService::setAssistantUid(int32_t uidAidl)
-{
-    uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
-    Mutex::Autolock _l(mLock);
-    mUidPolicy->setAssistantUid(uid);
+Status convertInt32VectorToUidVectorWithLimit(
+        const std::vector<int32_t>& uidsAidl, std::vector<uid_t>& uids) {
+    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+        convertRangeWithLimit(uidsAidl.begin(),
+            uidsAidl.end(),
+            std::back_inserter(uids),
+            aidl2legacy_int32_t_uid_t,
+            MAX_ITEMS_PER_LIST)));
+
     return Status::ok();
 }
 
-Status AudioPolicyService::setHotwordDetectionServiceUid(int32_t uidAidl)
+Status AudioPolicyService::setAssistantServicesUids(const std::vector<int32_t>& uidsAidl)
 {
-    uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
+    std::vector<uid_t> uids;
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
+
     Mutex::Autolock _l(mLock);
-    mUidPolicy->setHotwordDetectionServiceUid(uid);
+    mUidPolicy->setAssistantUids(uids);
+    return Status::ok();
+}
+
+Status AudioPolicyService::setActiveAssistantServicesUids(
+        const std::vector<int32_t>& activeUidsAidl) {
+    std::vector<uid_t> activeUids;
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(activeUidsAidl, activeUids));
+
+    Mutex::Autolock _l(mLock);
+    mUidPolicy->setActiveAssistantUids(activeUids);
     return Status::ok();
 }
 
 Status AudioPolicyService::setA11yServicesUids(const std::vector<int32_t>& uidsAidl)
 {
-    size_t size = uidsAidl.size();
-    if (size > MAX_ITEMS_PER_LIST) {
-        size = MAX_ITEMS_PER_LIST;
-    }
     std::vector<uid_t> uids;
-    RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
-            convertRange(uidsAidl.begin(),
-                         uidsAidl.begin() + size,
-                         std::back_inserter(uids),
-                         aidl2legacy_int32_t_uid_t)));
+    RETURN_IF_BINDER_ERROR(convertInt32VectorToUidVectorWithLimit(uidsAidl, uids));
+
     Mutex::Autolock _l(mLock);
     mUidPolicy->setA11yUids(uids);
     return Status::ok();
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 8add137..8263ad1 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -594,6 +594,8 @@
     }
 
     write(fd, result.string(), result.size());
+
+    mUidPolicy->dumpInternals(fd);
     return NO_ERROR;
 }
 
@@ -607,13 +609,20 @@
 {
 //    Go over all active clients and allow capture (does not force silence) in the
 //    following cases:
-//    The client is the assistant
+//    The client is in the active assistant list
+//         AND is TOP
+//               AND an accessibility service is TOP
+//                  AND source is either VOICE_RECOGNITION OR HOTWORD
+//               OR there is no active privacy sensitive capture or call
+//                          OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//                  AND source is VOICE_RECOGNITION OR HOTWORD
+//    The client is an assistant AND active assistant is not being used
 //        AND an accessibility service is on TOP or a RTT call is active
 //                AND the source is VOICE_RECOGNITION or HOTWORD
-//            OR uses VOICE_RECOGNITION AND is on TOP
-//                OR uses HOTWORD
-//            AND there is no active privacy sensitive capture or call
+//        OR there is no active privacy sensitive capture or call
 //                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+//            AND is TOP most recent assistant and uses VOICE_RECOGNITION or HOTWORD
+//                OR there is no top recent assistant and source is HOTWORD
 //    OR The client is an accessibility service
 //        AND Is on TOP
 //                AND the source is VOICE_RECOGNITION or HOTWORD
@@ -641,13 +650,16 @@
     sp<AudioRecordClient> latestActive;
     sp<AudioRecordClient> topSensitiveActive;
     sp<AudioRecordClient> latestSensitiveActiveOrComm;
+    sp<AudioRecordClient> latestActiveAssistant;
 
     nsecs_t topStartNs = 0;
     nsecs_t latestStartNs = 0;
     nsecs_t topSensitiveStartNs = 0;
     nsecs_t latestSensitiveStartNs = 0;
+    nsecs_t latestAssistantStartNs = 0;
     bool isA11yOnTop = mUidPolicy->isA11yOnTop();
     bool isAssistantOnTop = false;
+    bool useActiveAssistantList = false;
     bool isSensitiveActive = false;
     bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
     bool isInCommunication = mPhoneState == AUDIO_MODE_IN_COMMUNICATION;
@@ -682,6 +694,7 @@
         // for top or latest active to avoid masking regular clients started before
         if (!isAccessibility && !isVirtualSource(current->attributes.source)) {
             bool isAssistant = mUidPolicy->isAssistantUid(currentUid);
+            bool isActiveAssistant = mUidPolicy->isActiveAssistantUid(currentUid);
             bool isPrivacySensitive =
                     (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
 
@@ -699,6 +712,14 @@
                 }
                 if (isAssistant) {
                     isAssistantOnTop = true;
+                    if (isActiveAssistant) {
+                        useActiveAssistantList = true;
+                    } else if (!useActiveAssistantList) {
+                        if (current->startTimeNs > latestAssistantStartNs) {
+                            latestActiveAssistant = current;
+                            latestAssistantStartNs = current->startTimeNs;
+                        }
+                    }
                 }
             }
             // Clients capturing for HOTWORD are not considered
@@ -778,6 +799,8 @@
             current->attributionSource.uid == topActive->attributionSource.uid;
         bool isTopOrLatestSensitive = topSensitiveActive == nullptr ? false :
             current->attributionSource.uid == topSensitiveActive->attributionSource.uid;
+        bool isTopOrLatestAssistant = latestActiveAssistant == nullptr ? false :
+            current->attributionSource.uid == latestActiveAssistant->attributionSource.uid;
 
         auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) REQUIRES(mLock) {
             uid_t recordUid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(
@@ -807,23 +830,45 @@
         } else if (isVirtualSource(source)) {
             // Allow capture for virtual (remote submix, call audio TX or RX...) sources
             allowCapture = true;
-        } else if (mUidPolicy->isAssistantUid(currentUid)) {
+        } else if (!useActiveAssistantList && mUidPolicy->isAssistantUid(currentUid)) {
             // For assistant allow capture if:
-            //     An accessibility service is on TOP or a RTT call is active
+            //     Active assistant list is not being used
+            //     AND accessibility service is on TOP or a RTT call is active
             //            AND the source is VOICE_RECOGNITION or HOTWORD
-            //     OR is on TOP AND uses VOICE_RECOGNITION
-            //            OR uses HOTWORD
-            //         AND there is no active privacy sensitive capture or call
-            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //     OR there is no active privacy sensitive capture or call
+            //          OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //            AND is latest TOP assistant AND
+            //               uses VOICE_RECOGNITION OR uses HOTWORD
+            //            OR there is no TOP assistant and uses HOTWORD
             if (isA11yOnTop || rttCallActive) {
                 if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
                     allowCapture = true;
                 }
-            } else {
-                if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
-                        source == AUDIO_SOURCE_HOTWORD)
-                        && !(isSensitiveActive && !current->canCaptureOutput)
+            } else if (!(isSensitiveActive && !current->canCaptureOutput)
+                    && canCaptureIfInCallOrCommunication(current)) {
+                if (isTopOrLatestAssistant
+                    && (source == AUDIO_SOURCE_VOICE_RECOGNITION
+                        || source == AUDIO_SOURCE_HOTWORD)) {
+                        allowCapture = true;
+                } else if (!isAssistantOnTop && (source == AUDIO_SOURCE_HOTWORD)) {
+                    allowCapture = true;
+                }
+            }
+        } else if (useActiveAssistantList && mUidPolicy->isActiveAssistantUid(currentUid)) {
+            // For assistant on active list and on top allow capture if:
+            //     An accessibility service is on TOP
+            //         AND the source is VOICE_RECOGNITION or HOTWORD
+            //     OR there is no active privacy sensitive capture or call
+            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+            //         AND uses VOICE_RECOGNITION OR uses HOTWORD
+            if (isA11yOnTop) {
+                if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+                    allowCapture = true;
+                }
+            } else if (!(isSensitiveActive && !current->canCaptureOutput)
                         && canCaptureIfInCallOrCommunication(current)) {
+                if ((source == AUDIO_SOURCE_VOICE_RECOGNITION) || (source == AUDIO_SOURCE_HOTWORD))
+                {
                     allowCapture = true;
                 }
             }
@@ -1036,7 +1081,8 @@
         case TRANSACTION_getSurroundFormats:
         case TRANSACTION_getReportedSurroundFormats:
         case TRANSACTION_setSurroundFormatEnabled:
-        case TRANSACTION_setAssistantUid:
+        case TRANSACTION_setAssistantServicesUids:
+        case TRANSACTION_setActiveAssistantServicesUids:
         case TRANSACTION_setA11yServicesUids:
         case TRANSACTION_setUidDeviceAffinities:
         case TRANSACTION_removeUidDeviceAffinities:
@@ -1474,6 +1520,66 @@
     return it != mA11yUids.end();
 }
 
+void AudioPolicyService::UidPolicy::setAssistantUids(const std::vector<uid_t>& uids) {
+    mAssistantUids.clear();
+    mAssistantUids = uids;
+}
+
+bool AudioPolicyService::UidPolicy::isAssistantUid(uid_t uid)
+{
+    std::vector<uid_t>::iterator it = find(mAssistantUids.begin(), mAssistantUids.end(), uid);
+    return it != mAssistantUids.end();
+}
+
+void AudioPolicyService::UidPolicy::setActiveAssistantUids(const std::vector<uid_t>& activeUids) {
+    mActiveAssistantUids = activeUids;
+}
+
+bool AudioPolicyService::UidPolicy::isActiveAssistantUid(uid_t uid)
+{
+    std::vector<uid_t>::iterator it = find(mActiveAssistantUids.begin(),
+            mActiveAssistantUids.end(), uid);
+    return it != mActiveAssistantUids.end();
+}
+
+void AudioPolicyService::UidPolicy::dumpInternals(int fd) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    auto appendUidsToResult = [&](const char* title, const std::vector<uid_t> &uids) {
+        snprintf(buffer, SIZE, "\t%s: \n", title);
+        result.append(buffer);
+        int counter = 0;
+        if (uids.empty()) {
+            snprintf(buffer, SIZE, "\t\tNo UIDs present.\n");
+            result.append(buffer);
+            return;
+        }
+        for (const auto &uid : uids) {
+            snprintf(buffer, SIZE, "\t\tUID[%d]=%d\n", counter++, uid);
+            result.append(buffer);
+        }
+    };
+
+    snprintf(buffer, SIZE, "UID Policy:\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmObserverRegistered=%s\n",(mObserverRegistered ? "True":"False"));
+    result.append(buffer);
+
+    appendUidsToResult("Assistants UIDs", mAssistantUids);
+    appendUidsToResult("Active Assistants UIDs", mActiveAssistantUids);
+
+    appendUidsToResult("Accessibility UIDs", mA11yUids);
+
+    snprintf(buffer, SIZE, "\tInput Method Service UID=%d\n", mCurrentImeUid);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\tIs RTT Enabled: %s\n", (mRttEnabled ? "True":"False"));
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+}
+
 // -----------  AudioPolicyService::SensorPrivacyService implementation ----------
 void AudioPolicyService::SensorPrivacyPolicy::registerSelf() {
     SensorPrivacyManager spm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 39f2c97..ae65a65 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -218,8 +218,8 @@
             std::vector<AudioFormatDescription>* _aidl_return) override;
     binder::Status setSurroundFormatEnabled(const AudioFormatDescription& audioFormat,
                                             bool enabled) override;
-    binder::Status setAssistantUid(int32_t uid) override;
-    binder::Status setHotwordDetectionServiceUid(int32_t uid) override;
+    binder::Status setAssistantServicesUids(const std::vector<int32_t>& uids) override;
+    binder::Status setActiveAssistantServicesUids(const std::vector<int32_t>& activeUids) override;
     binder::Status setA11yServicesUids(const std::vector<int32_t>& uids) override;
     binder::Status setCurrentImeUid(int32_t uid) override;
     binder::Status isHapticPlaybackSupported(bool* _aidl_return) override;
@@ -420,7 +420,7 @@
     public:
         explicit UidPolicy(wp<AudioPolicyService> service)
                 : mService(service), mObserverRegistered(false),
-                  mAssistantUid(0), mHotwordDetectionServiceUid(0), mCurrentImeUid(0),
+                  mCurrentImeUid(0),
                   mRttEnabled(false) {}
 
         void registerSelf();
@@ -431,13 +431,10 @@
 
         bool isUidActive(uid_t uid);
         int getUidState(uid_t uid);
-        void setAssistantUid(uid_t uid) { mAssistantUid = uid; };
-        void setHotwordDetectionServiceUid(uid_t uid) { mHotwordDetectionServiceUid = uid; }
-        bool isAssistantUid(uid_t uid) const {
-            // The HotwordDetectionService is part of the Assistant package but runs with a separate
-            // (isolated) uid, so we check for either uid here.
-            return uid == mAssistantUid || uid == mHotwordDetectionServiceUid;
-        }
+        void setAssistantUids(const std::vector<uid_t>& uids);
+        bool isAssistantUid(uid_t uid);
+        void setActiveAssistantUids(const std::vector<uid_t>& activeUids);
+        bool isActiveAssistantUid(uid_t uid);
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
         bool isA11yUid(uid_t uid);
         bool isA11yOnTop();
@@ -459,6 +456,8 @@
         void updateUid(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
                        uid_t uid, bool active, int state, bool insert);
 
+        void dumpInternals(int fd);
+
      private:
         void notifyService();
         void updateOverrideUid(uid_t uid, bool active, bool insert);
@@ -472,8 +471,8 @@
         bool mObserverRegistered = false;
         std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
         std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
-        uid_t mAssistantUid = -1;
-        uid_t mHotwordDetectionServiceUid = -1;
+        std::vector<uid_t> mAssistantUids;
+        std::vector<uid_t> mActiveAssistantUids;
         std::vector<uid_t> mA11yUids;
         uid_t mCurrentImeUid = -1;
         bool mRttEnabled = false;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 8428881..3626378 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -49,6 +49,7 @@
         "common/CameraProviderManager.cpp",
         "common/FrameProcessorBase.cpp",
         "common/hidl/HidlProviderInfo.cpp",
+        "common/aidl/AidlProviderInfo.cpp",
         "api1/Camera2Client.cpp",
         "api1/client2/Parameters.cpp",
         "api1/client2/FrameProcessor.cpp",
@@ -84,6 +85,9 @@
         "device3/hidl/HidlCamera3Device.cpp",
         "device3/hidl/HidlCamera3OfflineSession.cpp",
         "device3/hidl/HidlCamera3OutputUtils.cpp",
+        "device3/aidl/AidlCamera3Device.cpp",
+        "device3/aidl/AidlCamera3OutputUtils.cpp",
+        "device3/aidl/AidlCamera3OfflineSession.cpp",
         "gui/RingBufferConsumer.cpp",
         "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
@@ -115,6 +119,7 @@
         "libutilscallstack",
         "libutils",
         "libbinder",
+        "libbinder_ndk",
         "libactivitymanager_aidl",
         "libpermission",
         "libcutils",
@@ -148,6 +153,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V1-ndk",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
@@ -155,10 +161,12 @@
         "android.hardware.camera.device@3.6",
         "android.hardware.camera.device@3.7",
         "android.hardware.camera.device@3.8",
+        "android.hardware.camera.device-V1-ndk",
         "media_permission-aidl-cpp",
     ],
 
     static_libs: [
+        "libaidlcommonsupport",
         "libprocessinfoservice_aidl",
         "libbinderthreadstateutils",
         "media_permission-aidl-cpp",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 5740038..271cfec 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -132,8 +132,9 @@
 static const String16
         sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
 const char *sFileName = "lastOpenSessionDumpFile";
-static constexpr int32_t kVendorClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
-static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
+static constexpr int32_t kSystemNativeClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
+static constexpr int32_t kSystemNativeClientState =
+        ActivityManager::PROCESS_STATE_PERSISTENT_UI;
 
 const String8 CameraService::kOfflineDevice("offline-");
 const String16 CameraService::kWatchAllClientsFlag("all");
@@ -155,6 +156,12 @@
     }
 }
 
+// The word 'System' here does not refer to clients only on the system
+// partition. They just need to have a android system uid.
+static bool doesClientHaveSystemUid() {
+    return (CameraThreadState::getCallingUid() < AID_APP_START);
+}
+
 void CameraService::onFirstRef()
 {
 
@@ -923,7 +930,7 @@
 }
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
-        const sp<IInterface>& cameraCb, const String16& packageName,
+        const sp<IInterface>& cameraCb, const String16& packageName, bool systemNativeClient,
         const std::optional<String16>& featureId,  const String8& cameraId,
         int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
         int servicePid, int deviceVersion, apiLevel effectiveApiLevel, bool overrideForPerfClass,
@@ -949,15 +956,14 @@
             if (effectiveApiLevel == API_1) { // Camera1 API route
                 sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                 *client = new Camera2Client(cameraService, tmp, packageName, featureId,
-                        cameraId, api1CameraId,
-                        facing, sensorOrientation, clientPid, clientUid,
+                        cameraId, api1CameraId, facing, sensorOrientation, clientPid, clientUid,
                         servicePid, overrideForPerfClass);
             } else { // Camera2 API route
                 sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                         static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
-                *client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
-                        cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid,
-                        overrideForPerfClass);
+                *client = new CameraDeviceClient(cameraService, tmp, packageName,
+                        systemNativeClient, featureId, cameraId, facing, sensorOrientation,
+                        clientPid, clientUid, servicePid, overrideForPerfClass);
             }
             break;
         default:
@@ -1053,7 +1059,7 @@
     sp<Client> tmp = nullptr;
     if (!(ret = connectHelper<ICameraClient,Client>(
             sp<ICameraClient>{nullptr}, id, cameraId,
-            internalPackageName, {}, uid, USE_CALLING_PID,
+            internalPackageName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
             API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
             /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*out*/ tmp)
             ).isOk()) {
@@ -1288,9 +1294,9 @@
 
     userid_t clientUserId = multiuser_get_user_id(clientUid);
 
-    // Only allow clients who are being used by the current foreground device user, unless calling
-    // from our own process OR the caller is using the cameraserver's HIDL interface.
-    if (getCurrentServingCall() != BinderCallType::HWBINDER && callingPid != getpid() &&
+    // For non-system clients : Only allow clients who are being used by the current foreground
+    // device user, unless calling from our own process.
+    if (!doesClientHaveSystemUid() && callingPid != getpid() &&
             (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
         ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
                 "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
@@ -1327,12 +1333,12 @@
 }
 
 void CameraService::finishConnectLocked(const sp<BasicClient>& client,
-        const CameraService::DescriptorPtr& desc, int oomScoreOffset) {
+        const CameraService::DescriptorPtr& desc, int oomScoreOffset, bool systemNativeClient) {
 
     // Make a descriptor for the incoming client
     auto clientDescriptor =
             CameraService::CameraClientManager::makeClientDescriptor(client, desc,
-                    oomScoreOffset);
+                    oomScoreOffset, systemNativeClient);
     auto evicted = mActiveClientManager.addAndEvict(clientDescriptor);
 
     logConnected(desc->getKey(), static_cast<int>(desc->getOwnerId()),
@@ -1362,7 +1368,7 @@
 
 status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
-        int oomScoreOffset,
+        int oomScoreOffset, bool systemNativeClient,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
@@ -1437,7 +1443,7 @@
         clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                 sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                 state->getConflicting(), actualScore, clientPid, actualState,
-                oomScoreOffset);
+                oomScoreOffset, systemNativeClient);
 
         resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
 
@@ -1580,7 +1586,7 @@
     String8 id = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
     ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
-            clientPackageName, {}, clientUid, clientPid, API_1,
+            clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1,
             /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, /*out*/client);
 
     if(!ret.isOk()) {
@@ -1612,14 +1618,14 @@
     // 1) If cameraserver tries to access this camera device, accept the
     //    connection.
     // 2) The camera device is a publicly hidden secure camera device AND some
-    //    component is trying to access it on a non-hwbinder thread (generally a non HAL client),
-    //    reject it.
+    //    non system component is trying to access it.
     // 3) if the camera device is advertised by the camera HAL as SYSTEM_ONLY
     //    and the serving thread is a non hwbinder thread, the client must have
     //    android.permission.SYSTEM_CAMERA permissions to connect.
 
     int cPid = CameraThreadState::getCallingPid();
     int cUid = CameraThreadState::getCallingUid();
+    bool systemClient = doesClientHaveSystemUid();
     SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
     if (getSystemCameraKind(cameraId, &systemCameraKind) != OK) {
         // This isn't a known camera ID, so it's not a system camera
@@ -1632,8 +1638,7 @@
         return false;
     }
     // (2)
-    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
-            systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
+    if (!systemClient && systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
         ALOGW("Rejecting access to secure hidden camera %s", cameraId.c_str());
         return true;
     }
@@ -1641,8 +1646,7 @@
     //     getCameraCharacteristics() allows for calls to succeed (albeit after hiding some
     //     characteristics) even if clients don't have android.permission.CAMERA. We do not want the
     //     same behavior for system camera devices.
-    if (getCurrentServingCall() != BinderCallType::HWBINDER &&
-            systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
+    if (!systemClient && systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
             !hasPermissionsForSystemCamera(cPid, cUid, /*logPermissionFailure*/true)) {
         ALOGW("Rejecting access to system only camera %s, inadequete permissions",
                 cameraId.c_str());
@@ -1667,11 +1671,12 @@
     sp<CameraDeviceClient> client = nullptr;
     String16 clientPackageNameAdj = clientPackageName;
     int callingPid = CameraThreadState::getCallingPid();
-
-    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
-        std::string vendorClient =
-                StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
-        clientPackageNameAdj = String16(vendorClient.c_str());
+    bool systemNativeClient = false;
+    if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
+        std::string systemClient =
+                StringPrintf("client.pid<%d>", CameraThreadState::getCallingPid());
+        clientPackageNameAdj = String16(systemClient.c_str());
+        systemNativeClient = true;
     }
 
     if (oomScoreOffset < 0) {
@@ -1695,7 +1700,7 @@
     }
 
     ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
-            /*api1CameraId*/-1, clientPackageNameAdj, clientFeatureId,
+            /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId,
             clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
             targetSdkVersion, /*out*/client);
 
@@ -1726,7 +1731,7 @@
 
 template<class CALLBACK, class CLIENT>
 Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-        int api1CameraId, const String16& clientPackageName,
+        int api1CameraId, const String16& clientPackageName, bool systemNativeClient,
         const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
         apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
         /*out*/sp<CLIENT>& device) {
@@ -1745,7 +1750,7 @@
     sp<CLIENT> client = nullptr;
     int facing = -1;
     int orientation = 0;
-    bool isNdk = (clientPackageName.size() == 0);
+    bool isNonSystemNdk = (clientPackageName.size() == 0);
     {
         // Acquire mServiceLock and prevent other clients from connecting
         std::unique_ptr<AutoConditionLock> lock =
@@ -1779,8 +1784,8 @@
         sp<BasicClient> clientTmp = nullptr;
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
         if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
-                IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, /*out*/&clientTmp,
-                /*out*/&partial)) != NO_ERROR) {
+                IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, systemNativeClient,
+                /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
             switch (err) {
                 case -ENODEV:
                     return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
@@ -1820,8 +1825,8 @@
         sp<BasicClient> tmp = nullptr;
         bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
                 mPerfClassPrimaryCameraIds, cameraId.string(), targetSdkVersion);
-        if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
-                cameraId, api1CameraId, facing, orientation,
+        if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
+                clientFeatureId, cameraId, api1CameraId, facing, orientation,
                 clientPid, clientUid, getpid(),
                 deviceVersion, effectiveApiLevel, overrideForPerfClass,
                 /*out*/&tmp)).isOk()) {
@@ -1923,7 +1928,7 @@
             mServiceLock.lock();
         } else {
             // Otherwise, add client to active clients list
-            finishConnectLocked(client, partial, oomScoreOffset);
+            finishConnectLocked(client, partial, oomScoreOffset, systemNativeClient);
         }
 
         client->setImageDumpMask(mImageDumpMask);
@@ -1935,7 +1940,7 @@
 
     int32_t openLatencyMs = ns2ms(systemTime() - openTimeNs);
     CameraServiceProxyWrapper::logOpen(cameraId, facing, clientPackageName,
-            effectiveApiLevel, isNdk, openLatencyMs);
+            effectiveApiLevel, isNonSystemNdk, openLatencyMs);
 
     {
         Mutex::Autolock lock(mInjectionParametersLock);
@@ -1998,7 +2003,8 @@
                 kOfflineDevice + onlineClientDesc->getKey(), offlineClient, /*cost*/ 0,
                 /*conflictingKeys*/ std::set<String8>(), onlinePriority.getScore(),
                 onlineClientDesc->getOwnerId(), onlinePriority.getState(),
-                /*ommScoreOffset*/ 0);
+                // native clients don't have offline processing support.
+                /*ommScoreOffset*/ 0, /*systemNativeClient*/false);
 
         // Allow only one offline device per camera
         auto incompatibleClients = mActiveClientManager.getIncompatibleClients(offlineClientDesc);
@@ -3169,7 +3175,7 @@
 
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
-        const String16& clientPackageName,
+        const String16& clientPackageName, bool systemNativeClient,
         const std::optional<String16>& clientFeatureId,
         const String8& cameraIdStr,
         int api1CameraId, int cameraFacing, int sensorOrientation,
@@ -3177,7 +3183,7 @@
         int servicePid) :
         CameraService::BasicClient(cameraService,
                 IInterface::asBinder(cameraClient),
-                clientPackageName, clientFeatureId,
+                clientPackageName, systemNativeClient, clientFeatureId,
                 cameraIdStr, cameraFacing, sensorOrientation,
                 clientPid, clientUid,
                 servicePid),
@@ -3207,13 +3213,14 @@
 
 CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
         const sp<IBinder>& remoteCallback,
-        const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
-        const String8& cameraIdStr, int cameraFacing, int sensorOrientation,
-        int clientPid, uid_t clientUid,
+        const String16& clientPackageName, bool nativeClient,
+        const std::optional<String16>& clientFeatureId, const String8& cameraIdStr,
+        int cameraFacing, int sensorOrientation, int clientPid, uid_t clientUid,
         int servicePid):
         mDestructionStarted(false),
         mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing), mOrientation(sensorOrientation),
-        mClientPackageName(clientPackageName), mClientFeatureId(clientFeatureId),
+        mClientPackageName(clientPackageName), mSystemNativeClient(nativeClient),
+        mClientFeatureId(clientFeatureId),
         mClientPid(clientPid), mClientUid(clientUid),
         mServicePid(servicePid),
         mDisconnected(false), mUidIsTrusted(false),
@@ -3256,7 +3263,19 @@
         }
         mClientPackageName = packages[0];
     }
-    if (getCurrentServingCall() != BinderCallType::HWBINDER) {
+
+    // There are 2 scenarios in which a client won't have AppOps operations
+    // (both scenarios : native clients)
+    //    1) It's an system native client*, the package name will be empty
+    //       and it will return from this function in the previous if condition
+    //       (This is the same as the previously existing behavior).
+    //    2) It is a system native client, but its package name has been
+    //       modified for debugging, however it still must not use AppOps since
+    //       the package name is not a real one.
+    //
+    //       * system native client - native client with UID < AID_APP_START. It
+    //         doesn't exclude clients not on the system partition.
+    if (!mSystemNativeClient) {
         mAppOpsManager = std::make_unique<AppOpsManager>();
     }
 
@@ -4078,23 +4097,23 @@
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const String8& key, const sp<BasicClient>& value, int32_t cost,
         const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
-        int32_t state, int32_t oomScoreOffset) {
+        int32_t state, int32_t oomScoreOffset, bool systemNativeClient) {
 
-    bool isVendorClient = getCurrentServingCall() == BinderCallType::HWBINDER;
-    int32_t score_adj = isVendorClient ? kVendorClientScore : score;
-    int32_t state_adj = isVendorClient ? kVendorClientState: state;
+    int32_t score_adj = systemNativeClient ? kSystemNativeClientScore : score;
+    int32_t state_adj = systemNativeClient ? kSystemNativeClientState: state;
 
     return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
-            key, value, cost, conflictingKeys, score_adj, ownerId, state_adj, isVendorClient,
-            oomScoreOffset);
+            key, value, cost, conflictingKeys, score_adj, ownerId, state_adj,
+            systemNativeClient, oomScoreOffset);
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial,
-        int32_t oomScoreOffset) {
+        int32_t oomScoreOffset, bool systemNativeClient) {
     return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
             partial->getConflicting(), partial->getPriority().getScore(),
-            partial->getOwnerId(), partial->getPriority().getState(), oomScoreOffset);
+            partial->getOwnerId(), partial->getPriority().getState(), oomScoreOffset,
+            systemNativeClient);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c73d28a..95d5101 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -350,6 +350,7 @@
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
                 const String16& clientPackageName,
+                bool nativeClient,
                 const std::optional<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int cameraFacing,
@@ -372,6 +373,7 @@
         const int                       mCameraFacing;
         const int                       mOrientation;
         String16                        mClientPackageName;
+        bool                            mSystemNativeClient;
         std::optional<String16>         mClientFeatureId;
         pid_t                           mClientPid;
         const uid_t                     mClientUid;
@@ -459,6 +461,7 @@
         Client(const sp<CameraService>& cameraService,
                 const sp<hardware::ICameraClient>& cameraClient,
                 const String16& clientPackageName,
+                bool systemNativeClient,
                 const std::optional<String16>& clientFeatureId,
                 const String8& cameraIdStr,
                 int api1CameraId,
@@ -542,14 +545,15 @@
          */
         static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
                 int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
-                int32_t ownerId, int32_t state, int oomScoreOffset);
+                int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient);
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
          * values intialized from a prior ClientDescriptor.
          */
         static DescriptorPtr makeClientDescriptor(const sp<BasicClient>& value,
-                const CameraService::DescriptorPtr& partial, int oomScoreOffset);
+                const CameraService::DescriptorPtr& partial, int oomScoreOffset,
+                bool systemNativeClient);
 
     }; // class CameraClientManager
 
@@ -783,7 +787,7 @@
     // Only call with with mServiceLock held.
     status_t handleEvictionsLocked(const String8& cameraId, int clientPid,
         apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
-        int scoreOffset,
+        int scoreOffset, bool systemNativeClient,
         /*out*/
         sp<BasicClient>* client,
         std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial);
@@ -815,7 +819,7 @@
     // Single implementation shared between the various connect calls
     template<class CALLBACK, class CLIENT>
     binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-            int api1CameraId, const String16& clientPackageName,
+            int api1CameraId, const String16& clientPackageName, bool systemNativeClient,
             const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
             apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
             /*out*/sp<CLIENT>& device);
@@ -892,7 +896,7 @@
      * This method must be called with mServiceLock held.
      */
     void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc,
-            int oomScoreOffset);
+            int oomScoreOffset, bool systemNativeClient);
 
     /**
      * Returns the underlying camera Id string mapped to a camera id int
@@ -1226,10 +1230,10 @@
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
             const sp<IInterface>& cameraCb, const String16& packageName,
-            const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
-            int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid,
-            int deviceVersion, apiLevel effectiveApiLevel, bool overrideForPerfClass,
-            /*out*/sp<BasicClient>* client);
+            bool systemNativeClient, const std::optional<String16>& featureId,
+            const String8& cameraId, int api1CameraId, int facing, int sensorOrientation,
+            int clientPid, uid_t clientUid, int servicePid, int deviceVersion,
+            apiLevel effectiveApiLevel, bool overrideForPerfClass, /*out*/sp<BasicClient>* client);
 
     status_t checkCameraAccess(const String16& opPackageName);
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 8c72bd7..5fcd43e 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -60,9 +60,10 @@
         uid_t clientUid,
         int servicePid,
         bool overrideForPerfClass):
-        Camera2ClientBase(cameraService, cameraClient, clientPackageName, clientFeatureId,
-                cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation,
-                clientPid, clientUid, servicePid, overrideForPerfClass, /*legacyClient*/ true),
+        Camera2ClientBase(cameraService, cameraClient, clientPackageName,
+                false/*systemNativeClient - since no ndk for api1*/, clientFeatureId,
+                cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
+                clientUid, servicePid, overrideForPerfClass, /*legacyClient*/ true),
         mParameters(api1CameraId, cameraFacing)
 {
     ATRACE_CALL();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index d26b730..223935d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -58,6 +58,7 @@
         const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        bool systemNativeClient,
         const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
@@ -69,6 +70,7 @@
     BasicClient(cameraService,
             IInterface::asBinder(remoteCallback),
             clientPackageName,
+            systemNativeClient,
             clientFeatureId,
             cameraId,
             cameraFacing,
@@ -86,6 +88,7 @@
 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        bool systemNativeClient,
         const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int cameraFacing,
@@ -94,8 +97,8 @@
         uid_t clientUid,
         int servicePid,
         bool overrideForPerfClass) :
-    Camera2ClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
-                cameraId, /*API1 camera ID*/ -1, cameraFacing, sensorOrientation,
+    Camera2ClientBase(cameraService, remoteCallback, clientPackageName, systemNativeClient,
+                clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing, sensorOrientation,
                 clientPid, clientUid, servicePid, overrideForPerfClass),
     mInputStream(),
     mStreamingRequestId(REQUEST_ID_NONE),
@@ -862,6 +865,7 @@
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
     int streamUseCase = outputConfiguration.getStreamUseCase();
     int timestampBase = outputConfiguration.getTimestampBase();
+    int mirrorMode = outputConfiguration.getMirrorMode();
 
     res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
             outputConfiguration.getSurfaceType());
@@ -906,7 +910,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
                 isStreamInfoValid, surface, bufferProducer, mCameraIdStr,
                 mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase, timestampBase);
+                streamUseCase, timestampBase, mirrorMode);
 
         if (!res.isOk())
             return res;
@@ -953,7 +957,7 @@
                 &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
                 outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
                 /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
-                streamInfo.timestampBase);
+                streamInfo.timestampBase, streamInfo.mirrorMode);
     }
 
     if (err != OK) {
@@ -979,7 +983,7 @@
                   streamInfo.height, streamInfo.format);
 
         // Set transform flags to ensure preview to be rotated correctly.
-        res = setStreamTransformLocked(streamId);
+        res = setStreamTransformLocked(streamId, streamInfo.mirrorMode);
 
         // Fill in mHighResolutionCameraIdToStreamIdSet map
         const String8 &cameraIdUsed =
@@ -1049,7 +1053,8 @@
             outputConfiguration.getSurfaceSetID(), isShared,
             outputConfiguration.isMultiResolution(), consumerUsage,
             outputConfiguration.getDynamicRangeProfile(),
-            outputConfiguration.getStreamUseCase());
+            outputConfiguration.getStreamUseCase(),
+            outputConfiguration.getMirrorMode());
 
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -1065,14 +1070,15 @@
                         overriddenSensorPixelModesUsed,
                         outputConfiguration.getDynamicRangeProfile(),
                         outputConfiguration.getStreamUseCase(),
-                        outputConfiguration.getTimestampBase()));
+                        outputConfiguration.getTimestampBase(),
+                        outputConfiguration.getMirrorMode()));
 
         ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
                 " (%d x %d) stream with format 0x%x.",
               __FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
 
         // Set transform flags to ensure preview to be rotated correctly.
-        res = setStreamTransformLocked(streamId);
+        res = setStreamTransformLocked(streamId, outputConfiguration.getMirrorMode());
 
         *newStreamId = streamId;
         // Fill in mHighResolutionCameraIdToStreamIdSet
@@ -1086,7 +1092,7 @@
     return res;
 }
 
-binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) {
+binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId, int mirrorMode) {
     int32_t transform = 0;
     status_t err;
     binder::Status res;
@@ -1095,7 +1101,7 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    err = getRotationTransformLocked(&transform);
+    err = getRotationTransformLocked(mirrorMode, &transform);
     if (err != OK) {
         // Error logged by getRotationTransformLocked.
         return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
@@ -1256,6 +1262,7 @@
     int streamUseCase = outputConfiguration.getStreamUseCase();
     int timestampBase = outputConfiguration.getTimestampBase();
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
+    int mirrorMode = outputConfiguration.getMirrorMode();
 
     for (size_t i = 0; i < newOutputsMap.size(); i++) {
         OutputStreamInfo outInfo;
@@ -1263,7 +1270,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
                 /*isStreamInfoValid*/ false, surface, newOutputsMap.valueAt(i), mCameraIdStr,
                 mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase, timestampBase);
+                streamUseCase, timestampBase, mirrorMode);
         if (!res.isOk())
             return res;
 
@@ -1623,6 +1630,7 @@
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
     int streamUseCase= outputConfiguration.getStreamUseCase();
     int timestampBase = outputConfiguration.getTimestampBase();
+    int mirrorMode = outputConfiguration.getMirrorMode();
     for (auto& bufferProducer : bufferProducers) {
         // Don't create multiple streams for the same target surface
         ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
@@ -1636,7 +1644,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
                 true /*isStreamInfoValid*/, surface, bufferProducer, mCameraIdStr,
                 mDevice->infoPhysical(physicalId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase, timestampBase);
+                streamUseCase, timestampBase, mirrorMode);
 
         if (!res.isOk())
             return res;
@@ -2118,11 +2126,12 @@
     return true;
 }
 
-status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
+status_t CameraDeviceClient::getRotationTransformLocked(int mirrorMode,
+        int32_t* transform) {
     ALOGV("%s: begin", __FUNCTION__);
 
     const CameraMetadata& staticInfo = mDevice->info();
-    return CameraUtils::getRotationTransform(staticInfo, transform);
+    return CameraUtils::getRotationTransform(staticInfo, mirrorMode, transform);
 }
 
 binder::Status CameraDeviceClient::mapRequestTemplate(int templateId,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1b0c61a..6675e24 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -50,6 +50,7 @@
     CameraDeviceClientBase(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            bool systemNativeClient,
             const std::optional<String16>& clientFeatureId,
             const String8& cameraId,
             int api1CameraId,
@@ -178,6 +179,7 @@
     CameraDeviceClient(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             const String16& clientPackageName,
+            bool clientPackageOverride,
             const std::optional<String16>& clientFeatureId,
             const String8& cameraId,
             int cameraFacing,
@@ -227,7 +229,7 @@
     virtual void          detachDevice();
 
     // Calculate the ANativeWindow transform from android.sensor.orientation
-    status_t              getRotationTransformLocked(/*out*/int32_t* transform);
+    status_t              getRotationTransformLocked(int mirrorMode, /*out*/int32_t* transform);
 
     bool isUltraHighResolutionSensor(const String8 &cameraId);
 
@@ -287,7 +289,7 @@
 
     // Set the stream transform flags to automatically rotate the camera stream for preview use
     // cases.
-    binder::Status setStreamTransformLocked(int streamId);
+    binder::Status setStreamTransformLocked(int streamId, int mirrorMode);
 
     // Utility method to insert the surface into SurfaceMap
     binder::Status insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 920a176..ef1d2de 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -54,7 +54,8 @@
             CameraService::BasicClient(
                     cameraService,
                     IInterface::asBinder(remoteCallback),
-                    clientPackageName, clientFeatureId,
+                    // (v)ndk doesn't have offline session support
+                    clientPackageName, /*overridePackageName*/false, clientFeatureId,
                     cameraIdStr, cameraFacing, sensorOrientation, clientPid, clientUid, servicePid),
             mRemoteCallback(remoteCallback), mOfflineSession(session),
             mCompositeStreamMap(offlineCompositeStreamMap) {}
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 55c7579..a29f3a6 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -34,6 +34,7 @@
 #include "api2/CameraDeviceClient.h"
 
 #include "device3/Camera3Device.h"
+#include "device3/aidl/AidlCamera3Device.h"
 #include "device3/hidl/HidlCamera3Device.h"
 #include "utils/CameraThreadState.h"
 #include "utils/CameraServiceProxyWrapper.h"
@@ -48,6 +49,7 @@
         const sp<CameraService>& cameraService,
         const sp<TCamCallbacks>& remoteCallback,
         const String16& clientPackageName,
+        bool systemNativeClient,
         const std::optional<String16>& clientFeatureId,
         const String8& cameraId,
         int api1CameraId,
@@ -58,9 +60,9 @@
         int servicePid,
         bool overrideForPerfClass,
         bool legacyClient):
-        TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
-                cameraId, api1CameraId, cameraFacing, sensorOrientation, clientPid, clientUid,
-                servicePid),
+        TClientBase(cameraService, remoteCallback, clientPackageName, systemNativeClient,
+                clientFeatureId, cameraId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
+                clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
         mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
         mDeviceActive(false), mApi1CameraId(api1CameraId)
@@ -118,8 +120,10 @@
                             mLegacyClient);
             break;
         case IPCTransport::AIDL:
-            ALOGE("%s: AIDL camera3Devices not available yet", __FUNCTION__);
-            return NO_INIT;
+            mDevice =
+                    new AidlCamera3Device(TClientBase::mCameraIdStr, mOverrideForPerfClass,
+                            mLegacyClient);
+             break;
         default:
             ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
                     TClientBase::mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 296ef43..182e6ef 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -48,6 +48,7 @@
     Camera2ClientBase(const sp<CameraService>& cameraService,
                       const sp<TCamCallbacks>& remoteCallback,
                       const String16& clientPackageName,
+                      bool systemNativeClient,
                       const std::optional<String16>& clientFeatureId,
                       const String8& cameraId,
                       int api1CameraId,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index baa21f0..bde0693 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -185,7 +185,8 @@
             uint64_t consumerUsage = 0,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) = 0;
 
     /**
      * Create an output stream of the requested size, format, rotation and
@@ -205,7 +206,8 @@
             uint64_t consumerUsage = 0,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) = 0;
 
     /**
      * Create an input stream of width, height, and format.
diff --git a/services/camera/libcameraservice/common/CameraProviderInfoTemplated.h b/services/camera/libcameraservice/common/CameraProviderInfoTemplated.h
new file mode 100644
index 0000000..db7692a
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraProviderInfoTemplated.h
@@ -0,0 +1,112 @@
+/*
+ * 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 ANDROID_SERVERS_CAMERA_CAMERAPROVIDERINFO_TEMPLATEDH
+#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDERINFO_TEMPLATEDH
+
+#include "common/CameraProviderManager.h"
+
+namespace android {
+
+template <class VendorTagSectionVectorType, class VendorTagSectionType>
+status_t IdlVendorTagDescriptor::createDescriptorFromIdl(
+        const VendorTagSectionVectorType& vts,
+        sp<VendorTagDescriptor>& descriptor) {
+
+    int 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);
+        return BAD_VALUE;
+    }
+
+    Vector<uint32_t> tagArray;
+    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+    sp<IdlVendorTagDescriptor> desc = new IdlVendorTagDescriptor();
+    desc->mTagCount = tagCount;
+
+    SortedVector<String8> sections;
+    KeyedVector<uint32_t, String8> tagToSectionMap;
+
+    int idx = 0;
+    for (size_t s = 0; s < vts.size(); s++) {
+        const VendorTagSectionType& section = vts[s];
+        const char *sectionName = section.sectionName.c_str();
+        if (sectionName == NULL) {
+            ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
+            return BAD_VALUE;
+        }
+        String8 sectionString(sectionName);
+        sections.add(sectionString);
+
+        for (size_t j = 0; j < section.tags.size(); j++) {
+            uint32_t tag = section.tags[j].tagId;
+            if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+                ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+                return BAD_VALUE;
+            }
+
+            tagArray.editItemAt(idx++) = section.tags[j].tagId;
+
+            const char *tagName = section.tags[j].tagName.c_str();
+            if (tagName == NULL) {
+                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);
+
+            int tagType = (int) section.tags[j].tagType;
+            if (tagType < 0 || tagType >= NUM_TYPES) {
+                ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+                return BAD_VALUE;
+            }
+            desc->mTagToTypeMap.add(tag, tagType);
+        }
+    }
+
+    desc->mSections = sections;
+
+    for (size_t i = 0; i < tagArray.size(); ++i) {
+        uint32_t tag = tagArray[i];
+        String8 sectionString = tagToSectionMap.valueFor(tag);
+
+        // Set up tag to section index map
+        ssize_t index = sections.indexOf(sectionString);
+        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+        // Set up reverse mapping
+        ssize_t reverseIndex = -1;
+        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+        }
+        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+    }
+
+    descriptor = std::move(desc);
+    return OK;
+}
+
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 4227d28..c337eda 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -20,15 +20,18 @@
 
 #include "CameraProviderManager.h"
 
+#include <aidl/android/hardware/camera/device/ICameraDevice.h>
 #include <android/hardware/camera/device/3.8/ICameraDevice.h>
 
 #include <algorithm>
 #include <chrono>
 #include "common/DepthPhotoProcessor.h"
 #include "hidl/HidlProviderInfo.h"
+#include "aidl/AidlProviderInfo.h"
 #include <dlfcn.h>
 #include <future>
 #include <inttypes.h>
+#include <android/binder_manager.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
 #include <functional>
@@ -59,12 +62,43 @@
 
 const float CameraProviderManager::kDepthARTolerance = .1f;
 
+// AIDL Devices start with major version 1, offset added to bring them up to HIDL.
+const uint16_t kAidlDeviceMajorOffset = 2;
+// AIDL Devices start with minor version 1, offset added to bring them up to HIDL.
+const uint16_t kAidlDeviceMinorOffset = 7;
+
 CameraProviderManager::HidlServiceInteractionProxyImpl
 CameraProviderManager::sHidlServiceInteractionProxy{};
 
 CameraProviderManager::~CameraProviderManager() {
 }
 
+const char* FrameworkTorchStatusToString(const TorchModeStatus& s) {
+    switch (s) {
+        case TorchModeStatus::NOT_AVAILABLE:
+            return "NOT_AVAILABLE";
+        case TorchModeStatus::AVAILABLE_OFF:
+            return "AVAILABLE_OFF";
+        case TorchModeStatus::AVAILABLE_ON:
+            return "AVAILABLE_ON";
+    }
+    ALOGW("Unexpected HAL torch mode status code %d", s);
+    return "UNKNOWN_STATUS";
+}
+
+const char* FrameworkDeviceStatusToString(const CameraDeviceStatus& s) {
+    switch (s) {
+        case CameraDeviceStatus::NOT_PRESENT:
+            return "NOT_PRESENT";
+        case CameraDeviceStatus::PRESENT:
+            return "PRESENT";
+        case CameraDeviceStatus::ENUMERATING:
+            return "ENUMERATING";
+    }
+    ALOGW("Unexpected HAL device status code %d", s);
+    return "UNKNOWN_STATUS";
+}
+
 hardware::hidl_vec<hardware::hidl_string>
 CameraProviderManager::HidlServiceInteractionProxyImpl::listServices() {
     hardware::hidl_vec<hardware::hidl_string> ret;
@@ -78,17 +112,9 @@
     return ret;
 }
 
-status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
-        HidlServiceInteractionProxy* hidlProxy) {
-    std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    if (hidlProxy == nullptr) {
-        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
-        return BAD_VALUE;
-    }
-    mListener = listener;
+status_t CameraProviderManager::tryToInitAndAddHidlProvidersLocked(
+        HidlServiceInteractionProxy *hidlProxy) {
     mHidlServiceProxy = hidlProxy;
-    mDeviceState = 0;
-
     // Registering will trigger notifications for all already-known providers
     bool success = mHidlServiceProxy->registerForNotifications(
         /* instance name, empty means no filter */ "",
@@ -102,10 +128,54 @@
     for (const auto& instance : mHidlServiceProxy->listServices()) {
         this->addHidlProviderLocked(instance);
     }
+    return OK;
+}
+
+static std::string getFullAidlProviderName(const std::string instance) {
+    std::string aidlHalServiceDescriptor =
+            std::string(aidl::android::hardware::camera::provider::ICameraProvider::descriptor);
+   return aidlHalServiceDescriptor + "/" + instance;
+}
+
+status_t CameraProviderManager::tryToAddAidlProvidersLocked() {
+    const char * aidlHalServiceDescriptor =
+            aidl::android::hardware::camera::provider::ICameraProvider::descriptor;
+    auto sm = defaultServiceManager();
+    auto aidlProviders = sm->getDeclaredInstances(
+            String16(aidlHalServiceDescriptor));
+    for (const auto &aidlInstance : aidlProviders) {
+        std::string aidlServiceName =
+                getFullAidlProviderName(std::string(String8(aidlInstance).c_str()));
+        auto res = sm->registerForNotifications(String16(aidlServiceName.c_str()), this);
+        if (res != OK) {
+            ALOGE("%s Unable to register for notifications with AIDL service manager",
+                    __FUNCTION__);
+            return res;
+        }
+        addAidlProviderLocked(aidlServiceName);
+    }
+    return OK;
+}
+
+status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
+        HidlServiceInteractionProxy* hidlProxy) {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+    if (hidlProxy == nullptr) {
+        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    mListener = listener;
+    mDeviceState = 0;
+    auto res = tryToInitAndAddHidlProvidersLocked(hidlProxy);
+    if (res != OK) {
+        // Logging done in called function;
+        return res;
+    }
+    res = tryToAddAidlProvidersLocked();
 
     IPCThreadState::self()->flushCommands();
 
-    return OK;
+    return res;
 }
 
 std::pair<int, int> CameraProviderManager::getCameraCount() const {
@@ -380,6 +450,22 @@
     return false;
 }
 
+template <class ProviderInfoType, class HalCameraProviderType>
+status_t CameraProviderManager::setTorchModeT(sp<ProviderInfo> &parentProvider,
+        std::shared_ptr<HalCameraProvider> *halCameraProvider) {
+    if (halCameraProvider == nullptr) {
+        return BAD_VALUE;
+    }
+    ProviderInfoType *idlProviderInfo = static_cast<ProviderInfoType *>(parentProvider.get());
+    auto idlInterface = idlProviderInfo->startProviderInterface();
+    if (idlInterface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    *halCameraProvider =
+            std::make_shared<HalCameraProviderType>(idlInterface, idlInterface->descriptor);
+    return OK;
+}
+
 status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled) {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
@@ -394,18 +480,19 @@
     }
     std::shared_ptr<HalCameraProvider> halCameraProvider = nullptr;
     IPCTransport providerTransport = parentProvider->getIPCTransport();
+    status_t res = OK;
     if (providerTransport == IPCTransport::HIDL) {
-        HidlProviderInfo * hidlProviderInfo = static_cast<HidlProviderInfo *>(parentProvider.get());
-        const sp<provider::V2_4::ICameraProvider> hidlInterface =
-                hidlProviderInfo->startProviderInterface();
-        if (hidlInterface == nullptr) {
-            return DEAD_OBJECT;
+        res = setTorchModeT<HidlProviderInfo, HidlHalCameraProvider>(parentProvider,
+                &halCameraProvider);
+        if (res != OK) {
+            return res;
         }
-        halCameraProvider =
-                std::make_shared<HidlHalCameraProvider>(hidlInterface, hidlInterface->descriptor);
     } else if (providerTransport == IPCTransport::AIDL) {
-        ALOGE("%s AIDL hal providers not supported yet", __FUNCTION__);
-        return INVALID_OPERATION;
+        res = setTorchModeT<AidlProviderInfo, AidlHalCameraProvider>(parentProvider,
+                &halCameraProvider);
+        if (res != OK) {
+            return res;
+        }
     } else {
         ALOGE("%s Invalid provider transport", __FUNCTION__);
         return INVALID_OPERATION;
@@ -518,6 +605,89 @@
     return res;
 }
 
+status_t CameraProviderManager::openAidlSession(const std::string &id,
+        const std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraDeviceCallback>& callback,
+        /*out*/
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession> *session) {
+
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+    auto deviceInfo = findDeviceInfoLocked(id,
+            /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
+    if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+    auto *aidlDeviceInfo3 = static_cast<AidlProviderInfo::AidlDeviceInfo3*>(deviceInfo);
+    sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto provider =
+            static_cast<AidlProviderInfo *>(parentProvider.get())->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    std::shared_ptr<HalCameraProvider> halCameraProvider =
+            std::make_shared<AidlHalCameraProvider>(provider, provider->descriptor);
+    saveRef(DeviceMode::CAMERA, id, halCameraProvider);
+
+    auto interface = aidlDeviceInfo3->startDeviceInterface();
+    if (interface == nullptr) {
+        removeRef(DeviceMode::CAMERA, id);
+        return DEAD_OBJECT;
+    }
+
+    auto ret = interface->open(callback, session);
+    if (!ret.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
+        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
+                __FUNCTION__, id.c_str(), ret.getMessage());
+        return DEAD_OBJECT;
+    }
+    return OK;
+}
+
+status_t CameraProviderManager::openAidlInjectionSession(const std::string &id,
+        const std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraDeviceCallback>& callback,
+        /*out*/
+        std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraInjectionSession> *session) {
+
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+    auto *aidlDeviceInfo3 = static_cast<AidlProviderInfo::AidlDeviceInfo3*>(deviceInfo);
+    sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+    if (parentProvider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto provider =
+            static_cast<AidlProviderInfo *>(parentProvider.get())->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    std::shared_ptr<HalCameraProvider> halCameraProvider =
+            std::make_shared<AidlHalCameraProvider>(provider, provider->descriptor);
+    saveRef(DeviceMode::CAMERA, id, halCameraProvider);
+
+    auto interface = aidlDeviceInfo3->startDeviceInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    auto ret = interface->openInjectionSession(callback, session);
+    if (!ret.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
+        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
+                __FUNCTION__, id.c_str(), ret.getMessage());
+        return DEAD_OBJECT;
+    }
+    return OK;
+}
+
 status_t CameraProviderManager::openHidlSession(const std::string &id,
         const sp<device::V3_2::ICameraDeviceCallback>& callback,
         /*out*/
@@ -622,6 +792,26 @@
     }
 }
 
+// We ignore sp<IBinder> param here since we need std::shared_ptr<...> which
+// will be retrieved through the ndk api through addAidlProviderLocked ->
+// tryToInitializeAidlProvider.
+void CameraProviderManager::onServiceRegistration(const String16 &name, const sp<IBinder>&) {
+    status_t res = OK;
+    std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
+    {
+        std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+        res = addAidlProviderLocked(String8(name).c_str());
+    }
+
+    sp<StatusListener> listener = getStatusListener();
+    if (nullptr != listener.get() && res == OK) {
+        listener->onNewProviderRegistered();
+    }
+
+    IPCThreadState::self()->flushCommands();
+}
+
 hardware::Return<void> CameraProviderManager::onRegistration(
         const hardware::hidl_string& /*fqName*/,
         const hardware::hidl_string& name,
@@ -653,6 +843,59 @@
     return OK;
 }
 
+void CameraProviderManager::ProviderInfo::initializeProviderInfoCommon(
+        const std::vector<std::string> &devices) {
+
+    sp<StatusListener> listener = mManager->getStatusListener();
+
+    for (auto& device : devices) {
+        std::string id;
+        status_t res = addDevice(device, CameraDeviceStatus::PRESENT, &id);
+        if (res != OK) {
+            ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
+                    __FUNCTION__, device.c_str(), strerror(-res), res);
+            continue;
+        }
+    }
+
+    ALOGI("Camera provider %s ready with %zu camera devices",
+            mProviderName.c_str(), mDevices.size());
+
+    // Process cached status callbacks
+    std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
+            std::make_unique<std::vector<CameraStatusInfoT>>();
+    {
+        std::lock_guard<std::mutex> lock(mInitLock);
+
+        for (auto& statusInfo : mCachedStatus) {
+            std::string id, physicalId;
+            status_t res = OK;
+            if (statusInfo.isPhysicalCameraStatus) {
+                res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+                    statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
+            } else {
+                res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
+            }
+            if (res == OK) {
+                cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
+                        id.c_str(), physicalId.c_str(), statusInfo.status);
+            }
+        }
+        mCachedStatus.clear();
+
+        mInitialized = true;
+    }
+
+    // The cached status change callbacks cannot be fired directly from this
+    // function, due to same-thread deadlock trying to acquire mInterfaceMutex
+    // twice.
+    if (listener != nullptr) {
+        mInitialStatusCallbackFuture = std::async(std::launch::async,
+                &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
+                listener, std::move(cachedStatus));
+    }
+}
+
 CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
         const std::string& id,
         hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {
@@ -1387,6 +1630,23 @@
     return falseRet;
 }
 
+status_t CameraProviderManager::tryToInitializeAidlProviderLocked(
+        const std::string& providerName, const sp<ProviderInfo>& providerInfo) {
+    using aidl::android::hardware::camera::provider::ICameraProvider;
+    std::shared_ptr<ICameraProvider> interface =
+            ICameraProvider::fromBinder(ndk::SpAIBinder(
+                    AServiceManager_getService(providerName.c_str())));
+
+    if (interface == nullptr) {
+        ALOGW("%s: AIDL Camera provider HAL '%s' is not actually available", __FUNCTION__,
+                providerName.c_str());
+        return BAD_VALUE;
+    }
+
+    AidlProviderInfo *aidlProviderInfo = static_cast<AidlProviderInfo *>(providerInfo.get());
+    return aidlProviderInfo->initializeAidlProvider(interface, mDeviceState);
+}
+
 status_t CameraProviderManager::tryToInitializeHidlProviderLocked(
         const std::string& providerName, const sp<ProviderInfo>& providerInfo) {
     sp<provider::V2_4::ICameraProvider> interface;
@@ -1395,7 +1655,7 @@
     if (interface == nullptr) {
         // The interface may not be started yet. In that case, this is not a
         // fatal error.
-        ALOGW("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
+        ALOGW("%s: HIDL Camera provider HAL '%s' is not actually available", __FUNCTION__,
                 providerName.c_str());
         return BAD_VALUE;
     }
@@ -1404,6 +1664,54 @@
     return hidlProviderInfo->initializeHidlProvider(interface, mDeviceState);
 }
 
+status_t CameraProviderManager::addAidlProviderLocked(const std::string& newProvider) {
+    // Several camera provider instances can be temporarily present.
+    // Defer initialization of a new instance until the older instance is properly removed.
+    auto providerInstance = newProvider + "-" + std::to_string(mProviderInstanceId);
+    bool providerPresent = false;
+    bool preexisting =
+            (mAidlProviderWithBinders.find(newProvider) != mAidlProviderWithBinders.end());
+
+    // We need to use the extracted provider name here since 'newProvider' has
+    // the fully qualified name of the provider service in case of AIDL. We want
+    // just instance name.
+    using aidl::android::hardware::camera::provider::ICameraProvider;
+    std::string extractedProviderName =
+            newProvider.substr(std::string(ICameraProvider::descriptor).size() + 1);
+    for (const auto& providerInfo : mProviders) {
+        if (providerInfo->mProviderName == extractedProviderName) {
+            ALOGW("%s: Camera provider HAL with name '%s' already registered",
+                    __FUNCTION__, newProvider.c_str());
+            // Do not add new instances for lazy HAL external provider or aidl
+            // binders previously seen.
+            if (preexisting || providerInfo->isExternalLazyHAL()) {
+                return ALREADY_EXISTS;
+            } else {
+                ALOGW("%s: The new provider instance will get initialized immediately after the"
+                        " currently present instance is removed!", __FUNCTION__);
+                providerPresent = true;
+                break;
+            }
+        }
+    }
+
+    sp<AidlProviderInfo> providerInfo =
+            new AidlProviderInfo(extractedProviderName, providerInstance, this);
+
+    if (!providerPresent) {
+        status_t res = tryToInitializeAidlProviderLocked(newProvider, providerInfo);
+        if (res != OK) {
+            return res;
+        }
+        mAidlProviderWithBinders.emplace(newProvider);
+    }
+
+    mProviders.push_back(providerInfo);
+    mProviderInstanceId++;
+
+    return OK;
+}
+
 status_t CameraProviderManager::addHidlProviderLocked(const std::string& newProvider,
         bool preexisting) {
     // Several camera provider instances can be temporarily present.
@@ -1467,9 +1775,13 @@
         for (const auto& providerInfo : mProviders) {
             if (providerInfo->mProviderName == removedProviderName) {
                 IPCTransport providerTransport = providerInfo->getIPCTransport();
+                std::string removedAidlProviderName = getFullAidlProviderName(removedProviderName);
                 switch(providerTransport) {
                     case IPCTransport::HIDL:
                         return tryToInitializeHidlProviderLocked(removedProviderName, providerInfo);
+                    case IPCTransport::AIDL:
+                        return tryToInitializeAidlProviderLocked(removedAidlProviderName,
+                                providerInfo);
                     default:
                         ALOGE("%s Unsupported Transport %d", __FUNCTION__, providerTransport);
                 }
@@ -1513,6 +1825,70 @@
     return mType;
 }
 
+status_t CameraProviderManager::ProviderInfo::addDevice(
+        const std::string& name, CameraDeviceStatus initialStatus,
+        /*out*/ std::string* parsedId) {
+
+    ALOGI("Enumerating new camera device: %s", name.c_str());
+
+    uint16_t major, minor;
+    std::string type, id;
+
+    status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+    if (res != OK) {
+        return res;
+    }
+    if (getIPCTransport() == IPCTransport::AIDL) {
+        // Till HIDL support exists, map AIDL versions to HIDL.
+        // TODO:b/196432585 Explore if we can get rid of this.
+        major += kAidlDeviceMajorOffset;
+        minor += kAidlDeviceMinorOffset;
+    }
+
+    if (type != mType) {
+        ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
+                type.c_str(), mType.c_str());
+        return BAD_VALUE;
+    }
+    if (mManager->isValidDeviceLocked(id, major)) {
+        ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
+                name.c_str(), id.c_str(), major);
+        return BAD_VALUE;
+    }
+
+    std::unique_ptr<DeviceInfo> deviceInfo;
+    switch (major) {
+        case 3:
+            deviceInfo = initializeDeviceInfo(name, mProviderTagid, id, minor);
+            break;
+        default:
+            ALOGE("%s: Device %s: Unsupported IDL device HAL major version %d:", __FUNCTION__,
+                    name.c_str(), major);
+            return BAD_VALUE;
+    }
+    if (deviceInfo == nullptr) return BAD_VALUE;
+    deviceInfo->notifyDeviceStateChange(getDeviceState());
+    deviceInfo->mStatus = initialStatus;
+    bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
+
+    mDevices.push_back(std::move(deviceInfo));
+
+    mUniqueCameraIds.insert(id);
+    if (isAPI1Compatible) {
+        // addDevice can be called more than once for the same camera id if HAL
+        // supports openLegacy.
+        if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
+                id) == mUniqueAPI1CompatibleCameraIds.end()) {
+            mUniqueAPI1CompatibleCameraIds.push_back(id);
+        }
+    }
+
+    if (parsedId != nullptr) {
+        *parsedId = id;
+    }
+    return OK;
+}
+
 void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
     for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
         if ((*it)->mId == id) {
@@ -1643,6 +2019,197 @@
     return mConcurrentCameraIdCombinations;
 }
 
+void CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeInternal(
+        const std::string& cameraDeviceName, CameraDeviceStatus newStatus) {
+    sp<StatusListener> listener;
+    std::string id;
+    std::lock_guard<std::mutex> lock(mInitLock);
+    CameraDeviceStatus internalNewStatus = newStatus;
+    if (!mInitialized) {
+        mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
+                cameraDeviceName.c_str(), std::string().c_str(),
+                internalNewStatus);
+        return;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
+            return;
+        }
+        listener = mManager->getStatusListener();
+    }
+
+    // Call without lock held to allow reentrancy into provider manager
+    if (listener != nullptr) {
+        listener->onDeviceStatusChanged(String8(id.c_str()), internalNewStatus);
+    }
+}
+
+status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
+        std::string* id, const std::string& cameraDeviceName,
+        CameraDeviceStatus newStatus) {
+    bool known = false;
+    std::string cameraId;
+    for (auto& deviceInfo : mDevices) {
+        if (deviceInfo->mName == cameraDeviceName) {
+            Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
+            ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+                    FrameworkDeviceStatusToString(newStatus),
+                    FrameworkDeviceStatusToString(deviceInfo->mStatus));
+            deviceInfo->mStatus = newStatus;
+            // TODO: Handle device removal (NOT_PRESENT)
+            cameraId = deviceInfo->mId;
+            known = true;
+            deviceInfo->mIsDeviceAvailable =
+                (newStatus == CameraDeviceStatus::PRESENT);
+            deviceInfo->mDeviceAvailableSignal.signal();
+            break;
+        }
+    }
+    // Previously unseen device; status must not be NOT_PRESENT
+    if (!known) {
+        if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+            ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+                mProviderName.c_str(), cameraDeviceName.c_str());
+            return BAD_VALUE;
+        }
+        addDevice(cameraDeviceName, newStatus, &cameraId);
+    } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+        removeDevice(cameraId);
+    } else if (isExternalLazyHAL()) {
+        // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
+        // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
+        // notif. would overwrite it
+        return BAD_VALUE;
+    }
+
+    if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+        ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+                  __FUNCTION__, mProviderName.c_str());
+    }
+    *id = cameraId;
+    return OK;
+}
+
+void CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeInternal(
+        const std::string& cameraDeviceName,
+        const std::string& physicalCameraDeviceName,
+        CameraDeviceStatus newStatus) {
+    sp<StatusListener> listener;
+    std::string id;
+    std::string physicalId;
+    std::lock_guard<std::mutex> lock(mInitLock);
+    if (!mInitialized) {
+        mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
+                physicalCameraDeviceName, newStatus);
+        return;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+
+        if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
+                physicalCameraDeviceName, newStatus)) {
+            return;
+        }
+
+        listener = mManager->getStatusListener();
+    }
+    // Call without lock held to allow reentrancy into provider manager
+    if (listener != nullptr) {
+        listener->onDeviceStatusChanged(String8(id.c_str()),
+                String8(physicalId.c_str()), newStatus);
+    }
+    return;
+}
+
+status_t CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked(
+            std::string* id, std::string* physicalId,
+            const std::string& cameraDeviceName,
+            const std::string& physicalCameraDeviceName,
+            CameraDeviceStatus newStatus) {
+    bool known = false;
+    std::string cameraId;
+    for (auto& deviceInfo : mDevices) {
+        if (deviceInfo->mName == cameraDeviceName) {
+            cameraId = deviceInfo->mId;
+            if (!deviceInfo->mIsLogicalCamera) {
+                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+                return BAD_VALUE;
+            }
+            if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+                    physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+                return BAD_VALUE;
+            }
+            ALOGI("Camera device %s physical device %s status is now %s",
+                    cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+                    FrameworkDeviceStatusToString(newStatus));
+            known = true;
+            break;
+        }
+    }
+    // Previously unseen device; status must not be NOT_PRESENT
+    if (!known) {
+        ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+                mProviderName.c_str(), cameraDeviceName.c_str(),
+                physicalCameraDeviceName.c_str());
+        return BAD_VALUE;
+    }
+
+    *id = cameraId;
+    *physicalId = physicalCameraDeviceName.c_str();
+    return OK;
+}
+
+void CameraProviderManager::ProviderInfo::torchModeStatusChangeInternal(
+        const std::string& cameraDeviceName,
+        TorchModeStatus newStatus) {
+    sp<StatusListener> listener;
+    SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+    std::string id;
+    bool known = false;
+    {
+        // Hold mLock for accessing mDevices
+        std::lock_guard<std::mutex> lock(mLock);
+        for (auto& deviceInfo : mDevices) {
+            if (deviceInfo->mName == cameraDeviceName) {
+                ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
+                        FrameworkTorchStatusToString(newStatus));
+                id = deviceInfo->mId;
+                known = true;
+                systemCameraKind = deviceInfo->mSystemCameraKind;
+                if (TorchModeStatus::AVAILABLE_ON != newStatus) {
+                    mManager->removeRef(CameraProviderManager::DeviceMode::TORCH, id);
+                }
+                break;
+            }
+        }
+        if (!known) {
+            ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
+                    mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
+            return;
+        }
+        // no lock needed since listener is set up only once during
+        // CameraProviderManager initialization and then never changed till it is
+        // destructed.
+        listener = mManager->getStatusListener();
+     }
+    // Call without lock held to allow reentrancy into provider manager
+    // The problem with holding mLock here is that we
+    // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
+    // back into CameraProviderManager which might try to hold mLock again (eg:
+    // findDeviceInfo, which should be holding mLock while iterating through
+    // each provider's devices).
+    if (listener != nullptr) {
+        listener->onTorchStatusChanged(String8(id.c_str()), newStatus, systemCameraKind);
+    }
+    return;
+}
+
 void CameraProviderManager::ProviderInfo::notifyDeviceInfoStateChangeLocked(
         int64_t newDeviceState) {
     std::lock_guard<std::mutex> lock(mLock);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 4568209..3d108bd 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -33,6 +33,7 @@
 #include <utils/Errors.h>
 #include <android/hardware/ICameraService.h>
 #include <utils/IPCTransport.h>
+#include <aidl/android/hardware/camera/provider/ICameraProvider.h>
 #include <android/hardware/camera/common/1.0/types.h>
 #include <android/hardware/camera/provider/2.5/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
@@ -97,6 +98,26 @@
 #define CAMERA_DEVICE_API_VERSION_3_8 HARDWARE_DEVICE_API_VERSION(3, 8)
 
 /**
+ * The vendor tag descriptor class that takes HIDL/AIDL vendor tag information as
+ * input. Not part of VendorTagDescriptor class because that class is used
+ * in AIDL generated sources which don't have access to AIDL / HIDL headers.
+ */
+class IdlVendorTagDescriptor : public VendorTagDescriptor {
+public:
+    /**
+     * Create a VendorTagDescriptor object from the HIDL/AIDL VendorTagSection
+     * vector.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    template <class VendorTagSectionVectorType, class VendorTagSectionType>
+    static status_t createDescriptorFromIdl(
+            const VendorTagSectionVectorType& vts,
+            /*out*/
+            sp<VendorTagDescriptor>& descriptor);
+};
+
+/**
  * A manager for all camera providers available on an Android device.
  *
  * Responsible for enumerating providers and the individual camera devices
@@ -106,11 +127,13 @@
  * opening them for active use.
  *
  */
-class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification {
+class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification,
+        public virtual IServiceManager::LocalRegistrationCallback {
 public:
     // needs to be made friend strict since HidlProviderInfo needs to inherit
     // from CameraProviderManager::ProviderInfo which isn't a public member.
     friend struct HidlProviderInfo;
+    friend struct AidlProviderInfo;
     ~CameraProviderManager();
 
     // Tiny proxy for the static methods in a HIDL interface that communicate with the hardware
@@ -315,6 +338,18 @@
      */
     status_t notifyDeviceStateChange(int64_t newState);
 
+    status_t openAidlSession(const std::string &id,
+        const std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraDeviceCallback>& callback,
+        /*out*/
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession> *session);
+
+    status_t openAidlInjectionSession(const std::string &id,
+        const std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraDeviceCallback>& callback,
+        /*out*/
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraInjectionSession> *session);
+
     /**
      * Open an active session to a camera device.
      *
@@ -339,6 +374,9 @@
             const hardware::hidl_string& name,
             bool preexisting) override;
 
+    // LocalRegistrationCallback::onServiceRegistration
+    virtual void onServiceRegistration(const String16& name, const sp<IBinder> &binder) override;
+
     /**
      * Dump out information about available providers and devices
      */
@@ -402,6 +440,17 @@
         sp<hardware::camera::provider::V2_4::ICameraProvider> mCameraProvider;
     };
 
+    struct AidlHalCameraProvider : public HalCameraProvider {
+        AidlHalCameraProvider(
+                const std::shared_ptr<
+                        aidl::android::hardware::camera::provider::ICameraProvider> &provider,
+                const char *descriptor) :
+                HalCameraProvider(descriptor), mCameraProvider(provider) { };
+     private:
+        std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider> mCameraProvider;
+    };
+
+
     // Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
     // ICameraProvider alive while it is in use by the camera with the given ID for camera
     // capabilities
@@ -418,10 +467,11 @@
     std::mutex mProviderInterfaceMapLock;
     struct ProviderInfo : public virtual RefBase {
         friend struct HidlProviderInfo;
+        friend struct AidlProviderInfo;
         const std::string mProviderName;
         const std::string mProviderInstance;
         const metadata_vendor_id_t mProviderTagid;
-        int mMinorVersion;
+        int32_t mMinorVersion;
         sp<VendorTagDescriptor> mVendorTagDescriptor;
         bool mSetTorchModeSupported;
         bool mIsRemote;
@@ -436,6 +486,7 @@
 
         status_t dump(int fd, const Vector<String16>& args) const;
 
+        void initializeProviderInfoCommon(const std::vector<std::string> &devices);
         /**
          * Setup vendor tags for this provider
          */
@@ -452,6 +503,8 @@
 
         virtual bool successfullyStartedProviderInterface() = 0;
 
+        virtual int64_t getDeviceState() = 0;
+
         std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
 
         /**
@@ -469,7 +522,6 @@
                     const std::set<std::string>& perfClassPrimaryCameraIds,
                     int targetSdkVersion, bool *isSupported) = 0;
 
-
         /**
          * Remove all devices associated with this provider and notify listeners
          * with NOT_PRESENT state.
@@ -666,6 +718,14 @@
         // End of scope for mInitLock
 
         std::future<void> mInitialStatusCallbackFuture;
+
+        std::unique_ptr<ProviderInfo::DeviceInfo>
+        virtual initializeDeviceInfo(
+                const std::string &name, const metadata_vendor_id_t tagId,
+                const std::string &id, uint16_t minorVersion) = 0;
+
+        virtual status_t reCacheConcurrentStreamingCameraIdsLocked() = 0;
+
         void notifyInitialStatusChange(sp<StatusListener> listener,
                 std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus);
 
@@ -682,10 +742,46 @@
         // Generate vendor tag id
         static metadata_vendor_id_t generateVendorTagId(const std::string &name);
 
+        status_t addDevice(
+                const std::string& name, CameraDeviceStatus initialStatus,
+                /*out*/ std::string* parsedId);
+
+        void cameraDeviceStatusChangeInternal(const std::string& cameraDeviceName,
+                CameraDeviceStatus newStatus);
+
+        status_t cameraDeviceStatusChangeLocked(
+                std::string* id, const std::string& cameraDeviceName,
+                CameraDeviceStatus newStatus);
+
+        void physicalCameraDeviceStatusChangeInternal(const std::string& cameraDeviceName,
+                const std::string& physicalCameraDeviceName,
+                CameraDeviceStatus newStatus);
+
+      status_t physicalCameraDeviceStatusChangeLocked(
+            std::string* id, std::string* physicalId,
+            const std::string& cameraDeviceName,
+            const std::string& physicalCameraDeviceName,
+            CameraDeviceStatus newStatus);
+
+        void torchModeStatusChangeInternal(const std::string& cameraDeviceName,
+                TorchModeStatus newStatus);
+
         void removeDevice(std::string id);
 
     };
 
+    template <class ProviderInfoType, class HalCameraProviderType>
+    status_t setTorchModeT(sp<ProviderInfo> &parentProvider,
+            std::shared_ptr<HalCameraProvider> *halCameraProvider);
+
+    // Try to get hidl provider services declared. Expects mInterfaceMutex to be
+    // locked. Also registers for hidl provider service notifications.
+    status_t tryToInitAndAddHidlProvidersLocked(HidlServiceInteractionProxy *hidlProxy);
+
+    // Try to get aidl provider services declared. Expects mInterfaceMutex to be
+    // locked. Also registers for aidl provider service notifications.
+    status_t tryToAddAidlProvidersLocked();
+
     /**
      * Save the ICameraProvider while it is being used by a camera or torch client
      */
@@ -709,9 +805,14 @@
 
     status_t addHidlProviderLocked(const std::string& newProvider, bool preexisting = false);
 
+    status_t addAidlProviderLocked(const std::string& newProvider);
+
     status_t tryToInitializeHidlProviderLocked(const std::string& providerName,
             const sp<ProviderInfo>& providerInfo);
 
+    status_t tryToInitializeAidlProviderLocked(const std::string& providerName,
+            const sp<ProviderInfo>& providerInfo);
+
     bool isLogicalCameraLocked(const std::string& id, std::vector<std::string>* physicalCameraIds);
 
     // No method corresponding to the same provider / member belonging to the
@@ -725,6 +826,8 @@
 
     size_t mProviderInstanceId = 0;
     std::vector<sp<ProviderInfo>> mProviders;
+    // Provider names of AIDL providers with retrieved binders.
+    std::set<std::string> mAidlProviderWithBinders;
 
     static const char* deviceStatusToString(
         const hardware::camera::common::V1_0::CameraDeviceStatus&);
@@ -744,6 +847,8 @@
             std::vector<std::string>& systemCameraDeviceIds) const;
 
     status_t usbDeviceDetached(const std::string &usbDeviceId);
+    ndk::ScopedAStatus onAidlRegistration(const std::string& in_name,
+            const ::ndk::SpAIBinder& in_binder);
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/common/HalConversionsTemplated.h b/services/camera/libcameraservice/common/HalConversionsTemplated.h
new file mode 100644
index 0000000..96a715c
--- /dev/null
+++ b/services/camera/libcameraservice/common/HalConversionsTemplated.h
@@ -0,0 +1,97 @@
+/*
+ * 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 ANDROID_SERVERS_CAMERA_HAL_CONVERSION_TEMPLATED_H
+#define ANDROID_SERVERS_CAMERA_HAL_CONVERSION_TEMPLATED_H
+
+#include "common/CameraProviderManager.h"
+
+#include <device3/Camera3StreamInterface.h>
+
+namespace android {
+
+template <class HalCameraDeviceStatus>
+HalCameraDeviceStatus mapFrameworkToHalCameraDeviceStatus(
+        const CameraDeviceStatus& s)  {
+    switch(s) {
+        case CameraDeviceStatus::PRESENT:
+            return HalCameraDeviceStatus::PRESENT;
+        case CameraDeviceStatus::NOT_PRESENT:
+            return HalCameraDeviceStatus::NOT_PRESENT;
+        case CameraDeviceStatus::ENUMERATING:
+            return HalCameraDeviceStatus::ENUMERATING;
+    }
+    ALOGW("Unexpectedcamera device status code %d", s);
+    return HalCameraDeviceStatus::NOT_PRESENT;
+}
+
+template <class HalCameraDeviceStatus>
+CameraDeviceStatus HalToFrameworkCameraDeviceStatus(
+        const HalCameraDeviceStatus& s)  {
+    switch(s) {
+        case HalCameraDeviceStatus::PRESENT:
+            return CameraDeviceStatus::PRESENT;
+        case HalCameraDeviceStatus::NOT_PRESENT:
+            return CameraDeviceStatus::NOT_PRESENT;
+        case HalCameraDeviceStatus::ENUMERATING:
+            return CameraDeviceStatus::ENUMERATING;
+    }
+    ALOGW("Unexpectedcamera device status code %d", s);
+    return CameraDeviceStatus::NOT_PRESENT;
+}
+
+template <class HalCameraResourceCost>
+CameraResourceCost HalToFrameworkResourceCost(
+        const HalCameraResourceCost& s)  {
+    CameraResourceCost internalResourceCost;
+    internalResourceCost.resourceCost = (uint32_t)s.resourceCost;
+    for (const auto device : s.conflictingDevices) {
+        internalResourceCost.conflictingDevices.emplace_back(device.c_str());
+    }
+    return internalResourceCost;
+}
+
+template <class HalTorchModeStatus>
+TorchModeStatus HalToFrameworkTorchModeStatus(
+        const HalTorchModeStatus& s)  {
+    switch(s) {
+        case HalTorchModeStatus::NOT_AVAILABLE:
+            return TorchModeStatus::NOT_AVAILABLE;
+        case HalTorchModeStatus::AVAILABLE_OFF:
+            return TorchModeStatus::AVAILABLE_OFF;
+        case HalTorchModeStatus::AVAILABLE_ON:
+            return TorchModeStatus::AVAILABLE_ON;
+    }
+    ALOGW("Unexpectedcamera torch mode status code %d", s);
+    return TorchModeStatus::NOT_AVAILABLE;
+}
+
+template <class HalCameraDeviceStatus>
+ const char* HalDeviceStatusToString(const HalCameraDeviceStatus& s) {
+    switch(s) {
+        case HalCameraDeviceStatus::NOT_PRESENT:
+            return "NOT_PRESENT";
+        case HalCameraDeviceStatus::PRESENT:
+            return "PRESENT";
+        case HalCameraDeviceStatus::ENUMERATING:
+            return "ENUMERATING";
+    }
+    ALOGW("Unexpected HAL device status code %d", s);
+    return "UNKNOWN_STATUS";
+}
+
+}
+
+#endif
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
new file mode 100644
index 0000000..0922b74
--- /dev/null
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "AidlProviderInfo.h"
+#include "common/HalConversionsTemplated.h"
+#include "common/CameraProviderInfoTemplated.h"
+
+#include <cutils/properties.h>
+
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_manager.h>
+#include <android/hardware/ICameraService.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/ZoomRatioMapper.h"
+#include <utils/SessionConfigurationUtils.h>
+#include <utils/Trace.h>
+
+namespace {
+const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+} // anonymous namespace
+
+namespace android {
+
+namespace SessionConfigurationUtils = ::android::camera3::SessionConfigurationUtils;
+
+using namespace aidl::android::hardware;
+using namespace hardware::camera;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::ICameraService;
+
+using HalDeviceStatusType = aidl::android::hardware::camera::common::CameraDeviceStatus;
+using ICameraProvider = aidl::android::hardware::camera::provider::ICameraProvider;
+using StatusListener = CameraProviderManager::StatusListener;
+
+status_t AidlProviderInfo::mapToStatusT(const ndk::ScopedAStatus& s) {
+    using Status = aidl::android::hardware::camera::common::Status;
+    Status st = static_cast<Status>(s.getServiceSpecificError());
+    switch(st) {
+        case Status::OK:
+            return OK;
+        case Status::ILLEGAL_ARGUMENT:
+            return BAD_VALUE;
+        case Status::CAMERA_IN_USE:
+            return -EBUSY;
+        case Status::MAX_CAMERAS_IN_USE:
+            return -EUSERS;
+        case Status::METHOD_NOT_SUPPORTED:
+            return UNKNOWN_TRANSACTION;
+        case Status::OPERATION_NOT_SUPPORTED:
+            return INVALID_OPERATION;
+        case Status::CAMERA_DISCONNECTED:
+            return DEAD_OBJECT;
+        case Status::INTERNAL_ERROR:
+            return INVALID_OPERATION;
+    }
+    ALOGW("Unexpected HAL status code %d", static_cast<int>(st));
+    return INVALID_OPERATION;
+}
+
+AidlProviderInfo::AidlProviderInfo(
+            const std::string &providerName,
+            const std::string &providerInstance,
+            CameraProviderManager *manager) :
+            CameraProviderManager::ProviderInfo(providerName, providerInstance, manager) {}
+
+status_t AidlProviderInfo::initializeAidlProvider(
+        std::shared_ptr<ICameraProvider>& interface, int64_t currentDeviceState) {
+
+    status_t res = parseProviderName(mProviderName, &mType, &mId);
+    if (res != OK) {
+        ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    ALOGI("Connecting to new camera provider: %s, isRemote? %d",
+            mProviderName.c_str(), interface->isRemote());
+
+    // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+    // before setCallback returns
+    mCallbacks =
+            ndk::SharedRefBase::make<AidlProviderCallbacks>(this);
+    ndk::ScopedAStatus status =
+            interface->setCallback(mCallbacks);
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), status.getMessage());
+        return mapToStatusT(status);
+    }
+
+    mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDied));
+    auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(), this);
+    if (link != STATUS_OK) {
+        ALOGW("%s: Unable to link to provider '%s' death notifications",
+                __FUNCTION__, mProviderName.c_str());
+        return DEAD_OBJECT;
+    }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    } else {
+        mActiveInterface = interface;
+    }
+
+    ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
+            __FUNCTION__, mProviderName.c_str(), mDeviceState);
+    notifyDeviceStateChange(currentDeviceState);
+
+    res = setUpVendorTags();
+    if (res != OK) {
+        ALOGE("%s: Unable to set up vendor tags from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return res;
+     }
+
+    // Get initial list of camera devices, if any
+    std::vector<std::string> devices;
+    std::vector<std::string> retDevices;
+    status = interface->getCameraIdList(&retDevices);
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), status.getMessage());
+        return mapToStatusT(status);
+    }
+
+    for (auto& name : retDevices) {
+        uint16_t major, minor;
+        std::string type, id;
+        status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+        if (res != OK) {
+            ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
+            return res;
+        } else {
+            devices.push_back(name);
+            mProviderPublicCameraIds.push_back(id);
+        }
+    }
+
+    // Get list of concurrent streaming camera device combinations
+    res = getConcurrentCameraIdsInternalLocked(interface);
+    if (res != OK) {
+        return res;
+    }
+
+    mSetTorchModeSupported = true;
+
+    mIsRemote = interface->isRemote();
+
+    initializeProviderInfoCommon(devices);
+    return OK;
+}
+
+void AidlProviderInfo::binderDied(void *cookie) {
+    AidlProviderInfo *provider = reinterpret_cast<AidlProviderInfo *>(cookie);
+    ALOGI("Camera provider '%s' has died; removing it", provider->mProviderInstance.c_str());
+    provider->mManager->removeProvider(provider->mProviderInstance);
+}
+
+status_t AidlProviderInfo::setUpVendorTags() {
+    if (mVendorTagDescriptor != nullptr)
+        return OK;
+
+    std::vector<camera::common::VendorTagSection> vts;
+    ::ndk::ScopedAStatus status;
+    const std::shared_ptr<ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    status = interface->getVendorTags(&vts);
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), status.getMessage());
+        return mapToStatusT(status);
+    }
+
+    // Read all vendor tag definitions into a descriptor
+    status_t res;
+    if ((res =
+            IdlVendorTagDescriptor::
+                    createDescriptorFromIdl<std::vector<camera::common::VendorTagSection>,
+                            camera::common::VendorTagSection>(vts, /*out*/mVendorTagDescriptor))
+            != OK) {
+        ALOGE("%s: Could not generate descriptor from vendor tag operations,"
+                "received error %s (%d). Camera clients will not be able to use"
+                "vendor tags", __FUNCTION__, strerror(res), res);
+        return res;
+    }
+
+    return OK;
+}
+
+status_t AidlProviderInfo::notifyDeviceStateChange(int64_t newDeviceState) {
+
+    mDeviceState = newDeviceState;
+    // Check if the provider is currently active - not going to start it up for this notification
+    auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock();
+    if (interface != nullptr) {
+        // Send current device state
+        interface->notifyDeviceStateChange(mDeviceState);
+    }
+    return OK;
+}
+
+bool AidlProviderInfo::successfullyStartedProviderInterface() {
+    return startProviderInterface() != nullptr;
+}
+
+std::shared_ptr<camera::device::ICameraDevice>
+AidlProviderInfo::startDeviceInterface(const std::string &name) {
+    ::ndk::ScopedAStatus status;
+    std::shared_ptr<camera::device::ICameraDevice> cameraInterface;
+    const std::shared_ptr<ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return nullptr;
+    }
+    status = interface->getCameraDeviceInterface(name, &cameraInterface);
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
+                __FUNCTION__, name.c_str(), status.getMessage());
+        return nullptr;
+    }
+    return cameraInterface;
+}
+
+const std::shared_ptr<ICameraProvider> AidlProviderInfo::startProviderInterface() {
+    ATRACE_CALL();
+    ALOGV("Request to start camera provider: %s", mProviderName.c_str());
+    if (mSavedInterface != nullptr) {
+        return mSavedInterface;
+    }
+    if (!kEnableLazyHal) {
+        ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
+        return nullptr;
+    }
+
+    auto interface = mActiveInterface.lock();
+    if (interface == nullptr) {
+        // Try to get service without starting
+        interface =
+                    ICameraProvider::fromBinder(
+                            ndk::SpAIBinder(AServiceManager_checkService(mProviderName.c_str())));
+        if (interface == nullptr) {
+            ALOGV("Camera provider actually needs restart, calling getService(%s)",
+                  mProviderName.c_str());
+            interface =
+                            ICameraProvider::fromBinder(
+                                    ndk::SpAIBinder(
+                                                AServiceManager_getService(mProviderName.c_str())));
+
+            // Set all devices as ENUMERATING, provider should update status
+            // to PRESENT after initializing.
+            // This avoids failing getCameraDeviceInterface_V3_x before devices
+            // are ready.
+            for (auto& device : mDevices) {
+              device->mIsDeviceAvailable = false;
+            }
+
+            interface->setCallback(mCallbacks);
+            auto link = AIBinder_linkToDeath(interface->asBinder().get(), mDeathRecipient.get(),
+                    this);
+            if (link != STATUS_OK) {
+                ALOGW("%s: Unable to link to provider '%s' death notifications",
+                        __FUNCTION__, mProviderName.c_str());
+                mManager->removeProvider(mProviderName);
+                return nullptr;
+            }
+
+            // Send current device state
+            interface->notifyDeviceStateChange(mDeviceState);
+        }
+        mActiveInterface = interface;
+    } else {
+        ALOGV("Camera provider (%s) already in use. Re-using instance.",
+              mProviderName.c_str());
+    }
+
+    return interface;
+}
+
+::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::cameraDeviceStatusChange(
+    const std::string& cameraDeviceName,
+    HalDeviceStatusType newStatus) {
+    sp<AidlProviderInfo> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: Parent provider not alive", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return parent->cameraDeviceStatusChange(cameraDeviceName, newStatus);
+}
+
+::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::torchModeStatusChange(
+            const std::string& cameraDeviceName,
+            aidl::android::hardware::camera::common::TorchModeStatus newStatus) {
+    sp<AidlProviderInfo> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: Parent provider not alive", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return parent->torchModeStatusChange(cameraDeviceName, newStatus);
+
+};
+
+::ndk::ScopedAStatus AidlProviderInfo::AidlProviderCallbacks::physicalCameraDeviceStatusChange(
+            const std::string& cameraDeviceName,
+            const std::string& physicalCameraDeviceName,
+            HalDeviceStatusType newStatus) {
+    sp<AidlProviderInfo> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: Parent provider not alive", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return parent->physicalCameraDeviceStatusChange(cameraDeviceName, physicalCameraDeviceName,
+            newStatus);
+};
+
+::ndk::ScopedAStatus AidlProviderInfo::cameraDeviceStatusChange(const std::string& cameraDeviceName,
+            HalDeviceStatusType newStatus) {
+    cameraDeviceStatusChangeInternal(cameraDeviceName, HalToFrameworkCameraDeviceStatus(newStatus));
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlProviderInfo::torchModeStatusChange(const std::string& cameraDeviceName,
+            aidl::android::hardware::camera::common::TorchModeStatus newStatus) {
+    torchModeStatusChangeInternal(cameraDeviceName, HalToFrameworkTorchModeStatus(newStatus));
+    return ::ndk::ScopedAStatus::ok();
+};
+
+::ndk::ScopedAStatus AidlProviderInfo::physicalCameraDeviceStatusChange(
+            const std::string& cameraDeviceName,
+            const std::string& physicalCameraDeviceName,
+            HalDeviceStatusType newStatus) {
+    physicalCameraDeviceStatusChangeInternal(cameraDeviceName, physicalCameraDeviceName,
+            HalToFrameworkCameraDeviceStatus(newStatus));
+    return ::ndk::ScopedAStatus::ok();
+};
+
+std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
+    AidlProviderInfo::initializeDeviceInfo(
+        const std::string &name, const metadata_vendor_id_t tagId,
+        const std::string &id, uint16_t minorVersion) {
+    ::ndk::ScopedAStatus status;
+
+    auto cameraInterface = startDeviceInterface(name);
+    if (cameraInterface == nullptr) return nullptr;
+
+    camera::common::CameraResourceCost resourceCost;
+    status = cameraInterface->getResourceCost(&resourceCost);
+    if (!status.isOk()) {
+        ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
+                name.c_str(), status.getMessage());
+        return nullptr;
+    }
+
+    for (auto& conflictName : resourceCost.conflictingDevices) {
+        uint16_t major, minor;
+        std::string type, id;
+        status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
+        if (res != OK) {
+            ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
+            return nullptr;
+        }
+        conflictName = id;
+    }
+
+    return std::unique_ptr<DeviceInfo3>(
+        new AidlDeviceInfo3(name, tagId, id, minorVersion, HalToFrameworkResourceCost(resourceCost),
+                this, mProviderPublicCameraIds, cameraInterface));
+}
+
+status_t AidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+
+    // Check if the provider is currently active - not going to start it up for this notification
+    auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock();
+    if (interface == nullptr) {
+        ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+                mProviderName.c_str());
+        return INVALID_OPERATION;
+    }
+
+    return getConcurrentCameraIdsInternalLocked(interface);
+}
+
+status_t AidlProviderInfo::getConcurrentCameraIdsInternalLocked(
+        std::shared_ptr<ICameraProvider> &interface) {
+    if (interface == nullptr) {
+        ALOGE("%s: null interface provided", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    std::vector<aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination> combs;
+    ::ndk::ScopedAStatus status = interface->getConcurrentCameraIds(&combs);
+
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return mapToStatusT(status);
+    }
+    mConcurrentCameraIdCombinations.clear();
+    for (const auto& combination : combs) {
+        std::unordered_set<std::string> deviceIds;
+        for (const auto &cameraDeviceId : combination.combination) {
+            deviceIds.insert(cameraDeviceId.c_str());
+        }
+        mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+    }
+
+    return OK;
+}
+
+AidlProviderInfo::AidlDeviceInfo3::AidlDeviceInfo3(
+        const std::string& name,
+        const metadata_vendor_id_t tagId,
+        const std::string &id, uint16_t minorVersion,
+        const CameraResourceCost& resourceCost,
+        sp<CameraProviderManager::ProviderInfo> parentProvider,
+        const std::vector<std::string>& publicCameraIds,
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice> interface) :
+        DeviceInfo3(name, tagId, id, minorVersion, resourceCost, parentProvider, publicCameraIds) {
+
+    // Get camera characteristics and initialize flash unit availability
+    aidl::android::hardware::camera::device::CameraMetadata chars;
+    ::ndk::ScopedAStatus status = interface->getCameraCharacteristics(&chars);
+    std::vector<uint8_t> &metadata = chars.metadata;
+    camera_metadata_t *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data());
+    size_t expectedSize = metadata.size();
+    int resV = validate_camera_metadata_structure(buffer, &expectedSize);
+    if (resV == OK || resV == CAMERA_METADATA_VALIDATION_SHIFTED) {
+        set_camera_metadata_vendor_id(buffer, mProviderTagid);
+        mCameraCharacteristics = buffer;
+    } else {
+        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+        return;
+    }
+
+    if (!status.isOk()) {
+        ALOGE("%s: Transaction error getting camera characteristics for device %s"
+                " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
+                status.getMessage());
+        return;
+    }
+
+    if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
+        const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
+        if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
+            for (size_t i = 0; i < stateMap.count; i += 2) {
+                mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
+            }
+        } else {
+            ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
+                    stateMap.count);
+        }
+    }
+
+    mSystemCameraKind = getSystemCameraKind();
+
+    status_t res = fixupMonochromeTags();
+    if (OK != res) {
+        ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return;
+    }
+    auto stat = addDynamicDepthTags();
+    if (OK != stat) {
+        ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
+                stat);
+    }
+    res = deriveHeicTags();
+    if (OK != res) {
+        ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+    }
+
+    if (camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
+        status_t status = addDynamicDepthTags(/*maxResolution*/true);
+        if (OK != status) {
+            ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
+                    __FUNCTION__, strerror(-status), status);
+        }
+
+        status = deriveHeicTags(/*maxResolution*/true);
+        if (OK != status) {
+            ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
+                    "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
+        }
+    }
+
+    res = addRotateCropTags();
+    if (OK != res) {
+        ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+    }
+    res = addPreCorrectionActiveArraySize();
+    if (OK != res) {
+        ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+    }
+    res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+            &mCameraCharacteristics, &mSupportNativeZoomRatio);
+    if (OK != res) {
+        ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+    }
+
+    camera_metadata_entry flashAvailable =
+            mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
+    if (flashAvailable.count == 1 &&
+            flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
+        mHasFlashUnit = true;
+    } else {
+        mHasFlashUnit = false;
+    }
+
+    camera_metadata_entry entry =
+            mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
+    if (entry.count == 1) {
+        mTorchDefaultStrengthLevel = entry.data.i32[0];
+    } else {
+        mTorchDefaultStrengthLevel = 0;
+    }
+    entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
+    if (entry.count == 1) {
+        mTorchMaximumStrengthLevel = entry.data.i32[0];
+    } else {
+        mTorchMaximumStrengthLevel = 0;
+    }
+
+    mTorchStrengthLevel = 0;
+
+    queryPhysicalCameraIds();
+
+    // Get physical camera characteristics if applicable
+    if (mIsLogicalCamera) {
+        for (auto& id : mPhysicalIds) {
+            if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
+                    mPublicCameraIds.end()) {
+                continue;
+            }
+
+            aidl::android::hardware::camera::device::CameraMetadata pChars;
+            status = interface->getPhysicalCameraCharacteristics(id, &pChars);
+            if (!status.isOk()) {
+                ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
+                        __FUNCTION__, id.c_str(), id.c_str(), status.getMessage());
+                return;
+            }
+            std::vector<uint8_t> &pMetadata = pChars.metadata;
+            camera_metadata_t *pBuffer =
+                    reinterpret_cast<camera_metadata_t*>(pMetadata.data());
+            size_t expectedSize = pMetadata.size();
+            int res = validate_camera_metadata_structure(pBuffer, &expectedSize);
+            if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+                set_camera_metadata_vendor_id(pBuffer, mProviderTagid);
+                mPhysicalCameraCharacteristics[id] = pBuffer;
+            } else {
+                ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+                return;
+            }
+
+            res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+                    &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
+            if (OK != res) {
+                ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+                        __FUNCTION__, strerror(-res), res);
+            }
+        }
+    }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    }
+}
+
+status_t AidlProviderInfo::AidlDeviceInfo3::setTorchMode(bool enabled) {
+    const std::shared_ptr<camera::device::ICameraDevice> interface = startDeviceInterface();
+    ::ndk::ScopedAStatus s = interface->setTorchMode(enabled);
+    if (!s.isOk()) {
+        ALOGE("%s Unable to set torch mode: %s", __FUNCTION__, s.getMessage());
+        return mapToStatusT(s);
+    }
+    return OK;
+}
+
+status_t AidlProviderInfo::AidlDeviceInfo3::turnOnTorchWithStrengthLevel(
+        int32_t torchStrength) {
+    const std::shared_ptr<camera::device::ICameraDevice> interface = startDeviceInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    ::ndk::ScopedAStatus s = interface->turnOnTorchWithStrengthLevel(torchStrength);
+    if (!s.isOk()) {
+        ALOGE("%s Unable to set torch mode strength %d : %s", __FUNCTION__, torchStrength,
+                s.getMessage());
+        return mapToStatusT(s);
+    }
+    mTorchStrengthLevel = torchStrength;
+    return OK;
+}
+
+status_t AidlProviderInfo::AidlDeviceInfo3::getTorchStrengthLevel(int32_t *torchStrength) {
+    if (torchStrength == nullptr) {
+        return BAD_VALUE;
+    }
+    const std::shared_ptr<camera::device::ICameraDevice> interface = startDeviceInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    ::ndk::ScopedAStatus status = interface->getTorchStrengthLevel(torchStrength);
+    if (!status.isOk()) {
+        ALOGE("%s: Couldn't get torch strength level: %s", __FUNCTION__, status.getMessage());
+        return mapToStatusT(status);
+    }
+    return OK;
+}
+
+std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
+AidlProviderInfo::AidlDeviceInfo3::startDeviceInterface() {
+    Mutex::Autolock l(mDeviceAvailableLock);
+    std::shared_ptr<camera::device::ICameraDevice> device;
+    ATRACE_CALL();
+    if (mSavedInterface == nullptr) {
+        sp<AidlProviderInfo> parentProvider =
+                static_cast<AidlProviderInfo *>(mParentProvider.promote().get());
+        if (parentProvider != nullptr) {
+            // Wait for lazy HALs to confirm device availability
+            if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
+                ALOGV("%s: Wait for external device to become available %s",
+                      __FUNCTION__,
+                      mId.c_str());
+
+                auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
+                                                         kDeviceAvailableTimeout);
+                if (res != OK) {
+                    ALOGE("%s: Failed waiting for device to become available",
+                          __FUNCTION__);
+                    return nullptr;
+                }
+            }
+
+            device = parentProvider->startDeviceInterface(mName);
+        }
+    } else {
+        device = mSavedInterface;
+    }
+    return device;
+}
+
+status_t AidlProviderInfo::AidlDeviceInfo3::dumpState(int fd) {
+    native_handle_t* handle = native_handle_create(1,0);
+    handle->data[0] = fd;
+    const std::shared_ptr<camera::device::ICameraDevice> interface = startDeviceInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    ::ndk::ScopedFileDescriptor sFd;
+    sFd.set(fcntl(fd, F_DUPFD_CLOEXEC, 0));
+    auto ret = interface->dumpState(sFd);
+    native_handle_delete(handle);
+    if (!ret.isOk()) {
+        return mapToStatusT(ret);
+    }
+    return OK;
+}
+
+status_t AidlProviderInfo::AidlDeviceInfo3::isSessionConfigurationSupported(
+        const SessionConfiguration &configuration, bool overrideForPerfClass, bool *status) {
+
+    camera::device::StreamConfiguration streamConfiguration;
+    bool earlyExit = false;
+    camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+          CameraMetadata physicalChars;
+          getPhysicalCameraCharacteristics(id.c_str(), &physicalChars);
+          return physicalChars;
+    };
+    auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
+            String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
+            streamConfiguration, overrideForPerfClass, &earlyExit);
+
+    if (!bRes.isOk()) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (earlyExit) {
+        *status = false;
+        return OK;
+    }
+
+    const std::shared_ptr<camera::device::ICameraDevice> interface =
+            startDeviceInterface();
+
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    ::ndk::ScopedAStatus ret =
+        interface->isStreamCombinationSupported(streamConfiguration, status);
+    if (!ret.isOk()) {
+        *status = false;
+        ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.getMessage());
+        return mapToStatusT(ret);
+    }
+    return OK;
+
+}
+
+status_t AidlProviderInfo::convertToAidlHALStreamCombinationAndCameraIdsLocked(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        const std::set<std::string>& perfClassPrimaryCameraIds,
+        int targetSdkVersion,
+        std::vector<camera::provider::CameraIdAndStreamCombination>
+                *halCameraIdsAndStreamCombinations,
+        bool *earlyExit) {
+    binder::Status bStatus = binder::Status::ok();
+    std::vector<camera::provider::CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
+    bool shouldExit = false;
+    status_t res = OK;
+    for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+        const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
+        camera::device::StreamConfiguration streamConfiguration;
+        CameraMetadata deviceInfo;
+        bool overrideForPerfClass =
+                SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+                        perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
+        res = mManager->getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
+        if (res != OK) {
+            return res;
+        }
+        camera3::metadataGetter getMetadata =
+                [this](const String8 &id, bool overrideForPerfClass) {
+                    CameraMetadata physicalDeviceInfo;
+                    mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+                                                   &physicalDeviceInfo);
+                    return physicalDeviceInfo;
+                };
+        std::vector<std::string> physicalCameraIds;
+        mManager->isLogicalCameraLocked(cameraId, &physicalCameraIds);
+        bStatus =
+            SessionConfigurationUtils::convertToHALStreamCombination(
+                    cameraIdAndSessionConfig.mSessionConfiguration,
+                    String8(cameraId.c_str()), deviceInfo, getMetadata,
+                    physicalCameraIds, streamConfiguration,
+                    overrideForPerfClass, &shouldExit);
+        if (!bStatus.isOk()) {
+            ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
+            return INVALID_OPERATION;
+        }
+        if (shouldExit) {
+            *earlyExit = true;
+            return OK;
+        }
+        camera::provider::CameraIdAndStreamCombination halCameraIdAndStream;
+        halCameraIdAndStream.cameraId = cameraId;
+        halCameraIdAndStream.streamConfiguration = streamConfiguration;
+        halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
+    }
+    *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
+    return OK;
+}
+
+status_t AidlProviderInfo::isConcurrentSessionConfigurationSupported(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        const std::set<std::string>& perfClassPrimaryCameraIds,
+        int targetSdkVersion, bool *isSupported) {
+
+      std::vector<camera::provider::CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
+      bool knowUnsupported = false;
+      status_t res = convertToAidlHALStreamCombinationAndCameraIdsLocked(
+              cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
+              targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
+      if (res != OK) {
+          ALOGE("%s unable to convert session configurations provided to HAL stream"
+                "combinations", __FUNCTION__);
+          return res;
+      }
+      if (knowUnsupported) {
+          // We got to know the streams aren't valid before doing the HAL
+          // call itself.
+          *isSupported = false;
+          return OK;
+      }
+
+      // Check if the provider is currently active - not going to start it up for this notification
+      auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.lock();
+      if (interface == nullptr) {
+          // TODO: This might be some other problem
+          return INVALID_OPERATION;
+      }
+      ::ndk::ScopedAStatus status = interface->isConcurrentStreamCombinationSupported(
+              halCameraIdsAndStreamCombinations, isSupported);
+      if (!status.isOk()) {
+          *isSupported = false;
+          ALOGE("%s: hal interface session configuration query failed", __FUNCTION__);
+          return mapToStatusT(status);
+      }
+
+    return OK;
+}
+
+} //namespace android
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
new file mode 100644
index 0000000..aa71e85
--- /dev/null
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_AIDLPROVIDERINFOH
+#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_AIDLPROVIDERINFOH
+
+#include "common/CameraProviderManager.h"
+
+#include <aidl/android/hardware/camera/common/Status.h>
+#include <aidl/android/hardware/camera/provider/BnCameraProviderCallback.h>
+#include <aidl/android/hardware/camera/device/ICameraDevice.h>
+
+namespace android {
+
+struct AidlProviderInfo : public CameraProviderManager::ProviderInfo {
+    // Current overall Android device physical status
+    int64_t mDeviceState;
+
+    // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
+    std::weak_ptr<aidl::android::hardware::camera::provider::ICameraProvider> mActiveInterface;
+
+    std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider> mSavedInterface;
+
+    AidlProviderInfo(
+            const std::string &providerName,
+            const std::string &providerInstance,
+            CameraProviderManager *manager);
+
+    static status_t mapToStatusT(const ndk::ScopedAStatus& s);
+
+    // Start camera device interface, start the camera provider process for lazy
+    // hals, if needed
+    status_t initializeAidlProvider(
+        std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>& interface,
+        int64_t currentDeviceState);
+
+    static void binderDied(void *cookie);
+
+    virtual IPCTransport getIPCTransport() override {return IPCTransport::AIDL;}
+
+    const std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider>
+    startProviderInterface();
+
+    virtual status_t setUpVendorTags() override;
+    virtual status_t notifyDeviceStateChange(int64_t newDeviceState) override;
+
+    virtual bool successfullyStartedProviderInterface() override;
+
+    virtual int64_t getDeviceState() override { return mDeviceState; };
+
+    /**
+     * Query the camera provider for concurrent stream configuration support
+     */
+    virtual status_t isConcurrentSessionConfigurationSupported(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        const std::set<std::string>& perfClassPrimaryCameraIds,
+        int targetSdkVersion, bool *isSupported) override;
+
+    std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
+            startDeviceInterface(const std::string &deviceName);
+
+    // AIDL ICameraProviderCallback interface - these lock the parent
+    // mInterfaceMutex
+
+    ::ndk::ScopedAStatus cameraDeviceStatusChange(const std::string& cameraDeviceName,
+            ::aidl::android::hardware::camera::common::CameraDeviceStatus newStatus);
+
+    ::ndk::ScopedAStatus torchModeStatusChange(const std::string& cameraDeviceName,
+            ::aidl::android::hardware::camera::common::TorchModeStatus newStatus);
+
+    ::ndk::ScopedAStatus physicalCameraDeviceStatusChange(
+            const std::string& cameraDeviceName,
+            const std::string& physicalCameraDeviceName,
+            ::aidl::android::hardware::camera::common::CameraDeviceStatus newStatus);
+
+    struct AidlProviderCallbacks :
+            public aidl::android::hardware::camera::provider::BnCameraProviderCallback {
+        AidlProviderCallbacks(wp<AidlProviderInfo> parent) : mParent(parent) { }
+        virtual ::ndk::ScopedAStatus cameraDeviceStatusChange(const std::string& cameraDeviceName,
+                ::aidl::android::hardware::camera::common::CameraDeviceStatus newStatus) override;
+
+        virtual ::ndk::ScopedAStatus torchModeStatusChange(const std::string& cameraDeviceName,
+                ::aidl::android::hardware::camera::common::TorchModeStatus newStatus) override;
+
+        virtual ::ndk::ScopedAStatus physicalCameraDeviceStatusChange(
+                const std::string& cameraDeviceName,
+                const std::string& physicalCameraDeviceName,
+                ::aidl::android::hardware::camera::common::CameraDeviceStatus newStatus) override;
+
+       private:
+        wp<AidlProviderInfo> mParent = nullptr;
+
+    };
+
+    struct AidlDeviceInfo3 : public CameraProviderManager::ProviderInfo::DeviceInfo3 {
+
+        //TODO: fix init
+        const hardware::hidl_version mVersion = hardware::hidl_version{3, 2};
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
+                mSavedInterface = nullptr;
+
+        AidlDeviceInfo3(const std::string& , const metadata_vendor_id_t ,
+                const std::string &, uint16_t ,
+                const CameraResourceCost& ,
+                sp<ProviderInfo> ,
+                const std::vector<std::string>& ,
+                std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>);
+
+        ~AidlDeviceInfo3() {}
+
+        virtual status_t setTorchMode(bool enabled) override;
+        virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
+        virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
+
+        virtual status_t dumpState(int fd) override;
+
+        virtual status_t isSessionConfigurationSupported(
+                const SessionConfiguration &/*configuration*/,
+                bool overrideForPerfClass,
+                bool *status/*status*/);
+
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
+                startDeviceInterface();
+    };
+
+ private:
+
+    // Helper for initializeDeviceInfo to use the right CameraProvider get method.
+    virtual std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &,
+            const metadata_vendor_id_t , const std::string &,
+            uint16_t ) override;
+
+    virtual status_t reCacheConcurrentStreamingCameraIdsLocked() override;
+
+    //Expects to have mLock locked
+
+    status_t getConcurrentCameraIdsInternalLocked(
+        std::shared_ptr<aidl::android::hardware::camera::provider::ICameraProvider> &interface);
+
+    //expects to have mManager->mInterfaceMutex locked
+
+    status_t convertToAidlHALStreamCombinationAndCameraIdsLocked(
+        const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+        const std::set<std::string>& perfClassPrimaryCameraIds,
+        int targetSdkVersion,
+        std::vector<aidl::android::hardware::camera::provider::CameraIdAndStreamCombination>
+                *halCameraIdsAndStreamCombinations,
+        bool *earlyExit);
+    std::shared_ptr<AidlProviderCallbacks> mCallbacks = nullptr;
+    ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+};
+
+} // namespace android
+#endif
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index e8432a6..3c5ea75 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 #include "HidlProviderInfo.h"
+#include "common/HalConversionsTemplated.h"
+#include "common/CameraProviderInfoTemplated.h"
 
 #include <cutils/properties.h>
 
@@ -42,6 +44,7 @@
 
 
 using StatusListener = CameraProviderManager::StatusListener;
+using HalDeviceStatusType = android::hardware::camera::common::V1_0::CameraDeviceStatus;
 
 using hardware::camera::provider::V2_5::DeviceState;
 using hardware::ICameraService;
@@ -111,83 +114,6 @@
     return "UNKNOWN_ERROR";
 }
 
-static common::V1_0::CameraDeviceStatus mapToHidlCameraDeviceStatus(const CameraDeviceStatus& s)  {
-    switch(s) {
-        case CameraDeviceStatus::PRESENT:
-            return common::V1_0::CameraDeviceStatus::PRESENT;
-        case CameraDeviceStatus::NOT_PRESENT:
-            return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
-        case CameraDeviceStatus::ENUMERATING:
-            return common::V1_0::CameraDeviceStatus::ENUMERATING;
-    }
-    ALOGW("Unexpectedcamera device status code %d", s);
-    return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
-}
-
-static CameraDeviceStatus hidlToInternalCameraDeviceStatus(
-        const common::V1_0::CameraDeviceStatus& s)  {
-    switch(s) {
-        case common::V1_0::CameraDeviceStatus::PRESENT:
-            return CameraDeviceStatus::PRESENT;
-        case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
-            return CameraDeviceStatus::NOT_PRESENT;
-        case common::V1_0::CameraDeviceStatus::ENUMERATING:
-            return CameraDeviceStatus::ENUMERATING;
-    }
-    ALOGW("Unexpectedcamera device status code %d", s);
-    return CameraDeviceStatus::NOT_PRESENT;
-}
-
-static TorchModeStatus hidlToInternalTorchModeStatus(
-        const common::V1_0::TorchModeStatus& s)  {
-    switch(s) {
-        case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
-            return TorchModeStatus::NOT_AVAILABLE;
-        case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
-            return TorchModeStatus::AVAILABLE_OFF;
-        case common::V1_0::TorchModeStatus::AVAILABLE_ON:
-            return TorchModeStatus::AVAILABLE_ON;
-    }
-    ALOGW("Unexpectedcamera torch mode status code %d", s);
-    return TorchModeStatus::NOT_AVAILABLE;
-}
-
-static CameraResourceCost hidlToInternalResourceCost(
-        const common::V1_0::CameraResourceCost& s)  {
-    CameraResourceCost internalResourceCost;
-    internalResourceCost.resourceCost = s.resourceCost;
-    for (const auto device : s.conflictingDevices) {
-        internalResourceCost.conflictingDevices.emplace_back(device.c_str());
-    }
-    return internalResourceCost;
-}
-
-static const char* deviceStatusToString(const common::V1_0::CameraDeviceStatus& s) {
-    switch(s) {
-        case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
-            return "NOT_PRESENT";
-        case common::V1_0::CameraDeviceStatus::PRESENT:
-            return "PRESENT";
-        case common::V1_0::CameraDeviceStatus::ENUMERATING:
-            return "ENUMERATING";
-    }
-    ALOGW("Unexpected HAL device status code %d", s);
-    return "UNKNOWN_STATUS";
-}
-
-static const char* torchStatusToString(const common::V1_0::TorchModeStatus& s) {
-    switch(s) {
-        case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
-            return "NOT_AVAILABLE";
-        case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
-            return "AVAILABLE_OFF";
-        case common::V1_0::TorchModeStatus::AVAILABLE_ON:
-            return "AVAILABLE_ON";
-    }
-    ALOGW("Unexpected HAL torch mode status code %d", s);
-    return "UNKNOWN_STATUS";
-}
-
 status_t HidlProviderInfo::initializeHidlProvider(
         sp<provider::V2_4::ICameraProvider>& interface,
         int64_t currentDeviceState) {
@@ -326,55 +252,7 @@
 
     mIsRemote = interface->isRemote();
 
-    sp<StatusListener> listener = mManager->getStatusListener();
-    for (auto& device : devices) {
-        std::string id;
-        status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
-        if (res != OK) {
-            ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
-                    __FUNCTION__, device.c_str(), strerror(-res), res);
-            continue;
-        }
-    }
-
-    ALOGI("Camera provider %s ready with %zu camera devices",
-            mProviderName.c_str(), mDevices.size());
-
-    // Process cached status callbacks
-    std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
-            std::make_unique<std::vector<CameraStatusInfoT>>();
-    {
-        std::lock_guard<std::mutex> lock(mInitLock);
-
-        for (auto& statusInfo : mCachedStatus) {
-            std::string id, physicalId;
-            status_t res = OK;
-            if (statusInfo.isPhysicalCameraStatus) {
-                res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
-                    statusInfo.cameraId, statusInfo.physicalCameraId,
-                    mapToHidlCameraDeviceStatus(statusInfo.status));
-            } else {
-                res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId,
-                        mapToHidlCameraDeviceStatus(statusInfo.status));
-            }
-            if (res == OK) {
-                cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
-                        id.c_str(), physicalId.c_str(), statusInfo.status);
-            }
-        }
-        mCachedStatus.clear();
-
-        mInitialized = true;
-    }
-
-    // The cached status change callbacks cannot be fired directly from this
-    // function, due to same-thread deadlock trying to acquire mInterfaceMutex
-    // twice.
-    if (listener != nullptr) {
-        mInitialStatusCallbackFuture = std::async(std::launch::async,
-                &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
-                listener, std::move(cachedStatus));
-    }
+    initializeProviderInfoCommon(devices);
 
     return OK;
 }
@@ -409,7 +287,10 @@
 
     // Read all vendor tag definitions into a descriptor
     status_t res;
-    if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
+    if ((res = IdlVendorTagDescriptor::createDescriptorFromIdl<
+                hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>,
+                        hardware::camera::common::V1_0::VendorTagSection>(vts,
+                                /*out*/mVendorTagDescriptor))
             != OK) {
         ALOGE("%s: Could not generate descriptor from vendor tag operations,"
                 "received error %s (%d). Camera clients will not be able to use"
@@ -539,256 +420,25 @@
 
 hardware::Return<void> HidlProviderInfo::cameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
-        hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
-    sp<StatusListener> listener;
-    std::string id;
-    std::lock_guard<std::mutex> lock(mInitLock);
-    CameraDeviceStatus internalNewStatus = hidlToInternalCameraDeviceStatus(newStatus);
-    if (!mInitialized) {
-        mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
-                cameraDeviceName.c_str(), std::string().c_str(),
-                internalNewStatus);
-        return hardware::Void();
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mLock);
-        if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
-            return hardware::Void();
-        }
-        listener = mManager->getStatusListener();
-    }
-
-    // Call without lock held to allow reentrancy into provider manager
-    if (listener != nullptr) {
-        listener->onDeviceStatusChanged(String8(id.c_str()), internalNewStatus);
-    }
-
+        HalDeviceStatusType newStatus) {
+    cameraDeviceStatusChangeInternal(cameraDeviceName, HalToFrameworkCameraDeviceStatus(newStatus));
     return hardware::Void();
 }
 
-status_t HidlProviderInfo::addDevice(const std::string& name,
-        common::V1_0::CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
-
-    ALOGI("Enumerating new camera device: %s", name.c_str());
-
-    uint16_t major, minor;
-    std::string type, id;
-
-    status_t res = parseDeviceName(name, &major, &minor, &type, &id);
-    if (res != OK) {
-        return res;
-    }
-    if (type != mType) {
-        ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
-                type.c_str(), mType.c_str());
-        return BAD_VALUE;
-    }
-    if (mManager->isValidDeviceLocked(id, major)) {
-        ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
-                name.c_str(), id.c_str(), major);
-        return BAD_VALUE;
-    }
-
-    std::unique_ptr<DeviceInfo> deviceInfo;
-    switch (major) {
-        case 1:
-            ALOGE("%s: Device %s: Unsupported HIDL device HAL major version %d:", __FUNCTION__,
-                    name.c_str(), major);
-            return BAD_VALUE;
-        case 3:
-            deviceInfo = initializeDeviceInfo(name, mProviderTagid, id, minor);
-            break;
-        default:
-            ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
-                    name.c_str(), major);
-            return BAD_VALUE;
-    }
-    if (deviceInfo == nullptr) return BAD_VALUE;
-    deviceInfo->notifyDeviceStateChange(mDeviceState);
-    deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(initialStatus);
-    bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
-
-    mDevices.push_back(std::move(deviceInfo));
-
-    mUniqueCameraIds.insert(id);
-    if (isAPI1Compatible) {
-        // addDevice can be called more than once for the same camera id if HAL
-        // supports openLegacy.
-        if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
-                id) == mUniqueAPI1CompatibleCameraIds.end()) {
-            mUniqueAPI1CompatibleCameraIds.push_back(id);
-        }
-    }
-
-    if (parsedId != nullptr) {
-        *parsedId = id;
-    }
-    return OK;
-}
-
-status_t HidlProviderInfo::cameraDeviceStatusChangeLocked(
-        std::string* id, const hardware::hidl_string& cameraDeviceName,
-        hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
-    bool known = false;
-    std::string cameraId;
-    for (auto& deviceInfo : mDevices) {
-        if (deviceInfo->mName == cameraDeviceName) {
-            Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
-            ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
-                    deviceStatusToString(newStatus),
-                    deviceStatusToString(mapToHidlCameraDeviceStatus(deviceInfo->mStatus)));
-            deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(newStatus);
-            // TODO: Handle device removal (NOT_PRESENT)
-            cameraId = deviceInfo->mId;
-            known = true;
-            deviceInfo->mIsDeviceAvailable =
-                (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT);
-            deviceInfo->mDeviceAvailableSignal.signal();
-            break;
-        }
-    }
-    // Previously unseen device; status must not be NOT_PRESENT
-    if (!known) {
-        if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
-            ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
-                mProviderName.c_str(), cameraDeviceName.c_str());
-            return BAD_VALUE;
-        }
-        addDevice(cameraDeviceName, newStatus, &cameraId);
-    } else if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
-        removeDevice(cameraId);
-    } else if (isExternalLazyHAL()) {
-        // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
-        // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
-        // notif. would overwrite it
-        return BAD_VALUE;
-    }
-    if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
-        ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
-                  __FUNCTION__, mProviderName.c_str());
-    }
-    *id = cameraId;
-    return OK;
-}
-
 hardware::Return<void> HidlProviderInfo::physicalCameraDeviceStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         const hardware::hidl_string& physicalCameraDeviceName,
-        hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
-    sp<StatusListener> listener;
-    std::string id;
-    std::string physicalId;
-    std::lock_guard<std::mutex> lock(mInitLock);
-    CameraDeviceStatus newInternalStatus = hidlToInternalCameraDeviceStatus(newStatus);
-    if (!mInitialized) {
-        mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
-                physicalCameraDeviceName, newInternalStatus);
-        return hardware::Void();
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mLock);
-
-        if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
-                physicalCameraDeviceName, newStatus)) {
-            return hardware::Void();
-        }
-
-        listener = mManager->getStatusListener();
-    }
-    // Call without lock held to allow reentrancy into provider manager
-    if (listener != nullptr) {
-        listener->onDeviceStatusChanged(String8(id.c_str()),
-                String8(physicalId.c_str()), newInternalStatus);
-    }
+        HalDeviceStatusType newStatus) {
+    physicalCameraDeviceStatusChangeInternal(cameraDeviceName, physicalCameraDeviceName,
+            HalToFrameworkCameraDeviceStatus(newStatus));
     return hardware::Void();
 }
 
-status_t HidlProviderInfo::physicalCameraDeviceStatusChangeLocked(
-            std::string* id, std::string* physicalId,
-            const hardware::hidl_string& cameraDeviceName,
-            const hardware::hidl_string& physicalCameraDeviceName,
-            hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
-    bool known = false;
-    std::string cameraId;
-    for (auto& deviceInfo : mDevices) {
-        if (deviceInfo->mName == cameraDeviceName) {
-            cameraId = deviceInfo->mId;
-            if (!deviceInfo->mIsLogicalCamera) {
-                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
-                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
-                return BAD_VALUE;
-            }
-            if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
-                    physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
-                ALOGE("%s: Invalid combination of camera id %s, physical id %s",
-                        __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
-                return BAD_VALUE;
-            }
-            ALOGI("Camera device %s physical device %s status is now %s",
-                    cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
-                    deviceStatusToString(newStatus));
-            known = true;
-            break;
-        }
-    }
-    // Previously unseen device; status must not be NOT_PRESENT
-    if (!known) {
-        ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
-                mProviderName.c_str(), cameraDeviceName.c_str(),
-                physicalCameraDeviceName.c_str());
-        return BAD_VALUE;
-    }
-
-    *id = cameraId;
-    *physicalId = physicalCameraDeviceName.c_str();
-    return OK;
-}
-
 hardware::Return<void> HidlProviderInfo::torchModeStatusChange(
         const hardware::hidl_string& cameraDeviceName,
         hardware::camera::common::V1_0::TorchModeStatus newStatus) {
-    sp<StatusListener> listener;
-    SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
-    std::string id;
-    bool known = false;
-    {
-        // Hold mLock for accessing mDevices
-        std::lock_guard<std::mutex> lock(mLock);
-        for (auto& deviceInfo : mDevices) {
-            if (deviceInfo->mName == cameraDeviceName) {
-                ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
-                        torchStatusToString(newStatus));
-                id = deviceInfo->mId;
-                known = true;
-                systemCameraKind = deviceInfo->mSystemCameraKind;
-                if (hardware::camera::common::V1_0::TorchModeStatus::AVAILABLE_ON != newStatus) {
-                    mManager->removeRef(CameraProviderManager::DeviceMode::TORCH, id);
-                }
-                break;
-            }
-        }
-        if (!known) {
-            ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
-                    mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
-            return hardware::Void();
-        }
-        // no lock needed since listener is set up only once during
-        // CameraProviderManager initialization and then never changed till it is
-        // destructed.
-        listener = mManager->getStatusListener();
-     }
-    // Call without lock held to allow reentrancy into provider manager
-    // The problem with holding mLock here is that we
-    // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
-    // back into CameraProviderManager which might try to hold mLock again (eg:
-    // findDeviceInfo, which should be holding mLock while iterating through
-    // each provider's devices).
-    if (listener != nullptr) {
-        listener->onTorchStatusChanged(String8(id.c_str()),
-                hidlToInternalTorchModeStatus(newStatus), systemCameraKind);
-    }
+
+    torchModeStatusChangeInternal(cameraDeviceName, HalToFrameworkTorchModeStatus(newStatus));
     return hardware::Void();
 }
 
@@ -836,7 +486,7 @@
     }
 
     return std::unique_ptr<DeviceInfo3>(
-        new HidlDeviceInfo3(name, tagId, id, minorVersion, hidlToInternalResourceCost(resourceCost),
+        new HidlDeviceInfo3(name, tagId, id, minorVersion, HalToFrameworkResourceCost(resourceCost),
                 this, mProviderPublicCameraIds, cameraInterface));
 }
 
@@ -1474,91 +1124,4 @@
     return INVALID_OPERATION;
 }
 
-status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
-        const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
-        sp<VendorTagDescriptor>& descriptor) {
-
-    int 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);
-        return BAD_VALUE;
-    }
-
-    Vector<uint32_t> tagArray;
-    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
-            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
-
-
-    sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
-    desc->mTagCount = tagCount;
-
-    SortedVector<String8> sections;
-    KeyedVector<uint32_t, String8> tagToSectionMap;
-
-    int idx = 0;
-    for (size_t s = 0; s < vts.size(); s++) {
-        const common::V1_0::VendorTagSection& section = vts[s];
-        const char *sectionName = section.sectionName.c_str();
-        if (sectionName == NULL) {
-            ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
-            return BAD_VALUE;
-        }
-        String8 sectionString(sectionName);
-        sections.add(sectionString);
-
-        for (size_t j = 0; j < section.tags.size(); j++) {
-            uint32_t tag = section.tags[j].tagId;
-            if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
-                ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
-                return BAD_VALUE;
-            }
-
-            tagArray.editItemAt(idx++) = section.tags[j].tagId;
-
-            const char *tagName = section.tags[j].tagName.c_str();
-            if (tagName == NULL) {
-                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);
-
-            int tagType = (int) section.tags[j].tagType;
-            if (tagType < 0 || tagType >= NUM_TYPES) {
-                ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
-                return BAD_VALUE;
-            }
-            desc->mTagToTypeMap.add(tag, tagType);
-        }
-    }
-
-    desc->mSections = sections;
-
-    for (size_t i = 0; i < tagArray.size(); ++i) {
-        uint32_t tag = tagArray[i];
-        String8 sectionString = tagToSectionMap.valueFor(tag);
-
-        // Set up tag to section index map
-        ssize_t index = sections.indexOf(sectionString);
-        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
-        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
-
-        // Set up reverse mapping
-        ssize_t reverseIndex = -1;
-        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
-            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
-            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
-        }
-        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
-    }
-
-    descriptor = std::move(desc);
-    return OK;
-}
-
 } //namespace android
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
index 0ba2aff..4181fea 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -21,25 +21,6 @@
 
 namespace android {
 
-/**
- * The vendor tag descriptor class that takes HIDL vendor tag information as
- * input. Not part of VendorTagDescriptor class because that class is used
- * in AIDL generated sources which don't have access to HIDL headers.
- */
-class HidlVendorTagDescriptor : public VendorTagDescriptor {
-public:
-    /**
-     * Create a VendorTagDescriptor object from the HIDL VendorTagSection
-     * vector.
-     *
-     * Returns OK on success, or a negative error code.
-     */
-    static status_t createDescriptorFromHidl(
-            const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
-            /*out*/
-            sp<VendorTagDescriptor>& descriptor);
-};
-
 struct HidlProviderInfo : public CameraProviderManager::ProviderInfo,
             virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
             virtual public hardware::hidl_death_recipient {
@@ -70,6 +51,8 @@
 
     virtual bool successfullyStartedProviderInterface() override;
 
+    virtual int64_t getDeviceState() override {return mDeviceState;};
+
     virtual status_t setUpVendorTags() override;
     virtual status_t notifyDeviceStateChange(int64_t) override;
 
@@ -129,24 +112,10 @@
 
  private:
 
-    status_t cameraDeviceStatusChangeLocked(
-                std::string* , const hardware::hidl_string& ,
-                hardware::camera::common::V1_0::CameraDeviceStatus );
-
-    status_t physicalCameraDeviceStatusChangeLocked(
-                std::string* , std::string* ,
-                const hardware::hidl_string& ,
-                const hardware::hidl_string& ,
-                hardware::camera::common::V1_0::CameraDeviceStatus );
-
-   status_t addDevice(const std::string& ,
-            hardware::camera::common::V1_0::CameraDeviceStatus ,
-            /*out*/ std::string *);
-
-    std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &,
+    virtual std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &,
             const metadata_vendor_id_t , const std::string &,
-            uint16_t );
-    status_t reCacheConcurrentStreamingCameraIdsLocked();
+            uint16_t ) override;
+    virtual status_t reCacheConcurrentStreamingCameraIdsLocked() override;
 
     //Expects to have mLock locked
     status_t getConcurrentCameraIdsInternalLocked(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f31241c..a5c4e4d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -65,8 +65,6 @@
 #include "utils/TraceHFR.h"
 #include "utils/CameraServiceProxyWrapper.h"
 
-#include "../common/hidl/HidlProviderInfo.h"
-
 #include <algorithm>
 #include <tuple>
 
@@ -980,7 +978,8 @@
             const String8& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
-            uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
+            uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase,
+            int mirrorMode) {
     ATRACE_CALL();
 
     if (consumer == nullptr) {
@@ -994,7 +993,7 @@
     return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
             format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
             streamSetId, isShared, isMultiResolution, consumerUsage, dynamicRangeProfile,
-            streamUseCase, timestampBase);
+            streamUseCase, timestampBase, mirrorMode);
 }
 
 static bool isRawFormat(int format) {
@@ -1014,7 +1013,8 @@
         android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
         const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
-        uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
+        uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase,
+        int mirrorMode) {
     ATRACE_CALL();
 
     Mutex::Autolock il(mInterfaceLock);
@@ -1022,10 +1022,10 @@
     Mutex::Autolock l(mLock);
     ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
             " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d"
-            " dynamicRangeProfile %d, streamUseCase %d, timestampBase %d",
+            " dynamicRangeProfile %d, streamUseCase %d, timestampBase %d, mirrorMode %d",
             mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
             consumerUsage, isShared, physicalCameraId.string(), isMultiResolution,
-            dynamicRangeProfile, streamUseCase, timestampBase);
+            dynamicRangeProfile, streamUseCase, timestampBase, mirrorMode);
 
     status_t res;
     bool wasActive = false;
@@ -1095,7 +1095,7 @@
                 width, height, blobBufferSize, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
                 isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
-                timestampBase);
+                timestampBase, mirrorMode);
     } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
         bool maxResolution =
                 sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -1110,25 +1110,25 @@
                 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
                 isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
-                timestampBase);
+                timestampBase, mirrorMode);
     } else if (isShared) {
         newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
                 width, height, format, consumerUsage, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
                 mUseHalBufManager, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
-                timestampBase);
+                timestampBase, mirrorMode);
     } else if (consumers.size() == 0 && hasDeferredConsumer) {
         newStream = new Camera3OutputStream(mNextStreamId,
                 width, height, format, consumerUsage, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
                 isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
-                timestampBase);
+                timestampBase, mirrorMode);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
                 isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
-                timestampBase);
+                timestampBase, mirrorMode);
     }
 
     size_t consumerCount = consumers.size();
@@ -1247,7 +1247,7 @@
         CLOGE("Stream %d does not exist", id);
         return BAD_VALUE;
     }
-    return stream->setTransform(transform);
+    return stream->setTransform(transform, false /*mayChangeMirror*/);
 }
 
 status_t Camera3Device::deleteStream(int id) {
@@ -2737,11 +2737,7 @@
             physicalMetadata, outputBuffers, numOutputBuffers, inputStreamId);
 }
 
-/**
- * HalInterface inner class methods
- */
-
-void Camera3Device::HalInterface::cleanupNativeHandles(
+void Camera3Device::cleanupNativeHandles(
         std::vector<native_handle_t*> *handles, bool closeFd) {
     if (handles == nullptr) {
         return;
@@ -2758,6 +2754,10 @@
     return;
 }
 
+/**
+ * HalInterface inner class methods
+ */
+
 void Camera3Device::HalInterface::getInflightBufferKeys(
         std::vector<std::pair<int32_t, int32_t>>* out) {
     mBufferRecords.getInflightBufferKeys(out);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0f5e65b..be976d0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -78,11 +78,17 @@
             public camera3::RequestBufferInterface,
             public camera3::FlushBufferInterface {
   friend class HidlCamera3Device;
+  friend class AidlCamera3Device;
   public:
 
     explicit Camera3Device(const String8& id, bool overrideForPerfClass, bool legacyClient = false);
 
     virtual ~Camera3Device();
+    // Delete and optionally close native handles and clear the input vector afterward
+    static void cleanupNativeHandles(
+            std::vector<native_handle_t*> *handles, bool closeFd = false);
+
+    IPCTransport getTransportType() { return mInterface->getTransportType(); }
 
     /**
      * CameraDeviceBase interface
@@ -136,7 +142,8 @@
             int dynamicRangeProfile =
             ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) override;
 
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -150,7 +157,8 @@
             int dynamicRangeProfile =
             ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO) override;
 
     status_t createInputStream(
             uint32_t width, uint32_t height, int format, bool isMultiResolution,
@@ -450,10 +458,6 @@
             return OK;
         }
 
-        // Delete and optionally close native handles and clear the input vector afterward
-        static void cleanupNativeHandles(
-                std::vector<native_handle_t*> *handles, bool closeFd = false);
-
         virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
 
         std::mutex mFreedBuffersLock;
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 61e43cb..19afd69 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -76,7 +76,7 @@
     Camera3IOStreamBase::dump(fd, args);
 }
 
-status_t Camera3FakeStream::setTransform(int) {
+status_t Camera3FakeStream::setTransform(int, bool) {
     ATRACE_CALL();
     // Do nothing
     return OK;
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index df19c3d..48e44dc 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -52,7 +52,7 @@
 
     virtual void     dump(int fd, const Vector<String16> &args) const;
 
-    status_t         setTransform(int transform);
+    status_t         setTransform(int transform, bool mayChangeMirror);
 
     virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index a82d19b..9574309 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -47,7 +47,8 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+        int mirrorMode) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
@@ -60,6 +61,7 @@
         mTimestampOffset(timestampOffset),
         mConsumerUsage(0),
         mDropBuffers(false),
+        mMirrorMode(mirrorMode),
         mDequeueBufferLatency(kDequeueLatencyBinSize) {
 
     if (mConsumer == NULL) {
@@ -78,7 +80,8 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+        int mirrorMode) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
                             format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
                             setId, isMultiResolution, dynamicRangeProfile, streamUseCase,
@@ -90,6 +93,7 @@
         mTimestampOffset(timestampOffset),
         mConsumerUsage(0),
         mDropBuffers(false),
+        mMirrorMode(mirrorMode),
         mDequeueBufferLatency(kDequeueLatencyBinSize) {
 
     if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
@@ -114,7 +118,8 @@
         const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+        int mirrorMode) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
@@ -127,6 +132,7 @@
         mTimestampOffset(timestampOffset),
         mConsumerUsage(consumerUsage),
         mDropBuffers(false),
+        mMirrorMode(mirrorMode),
         mDequeueBufferLatency(kDequeueLatencyBinSize) {
     // Deferred consumer only support preview surface format now.
     if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
@@ -158,7 +164,8 @@
                                          uint64_t consumerUsage, nsecs_t timestampOffset,
                                          int setId, bool isMultiResolution,
                                          int dynamicRangeProfile, int streamUseCase,
-                                         bool deviceTimeBaseIsRealtime, int timestampBase) :
+                                         bool deviceTimeBaseIsRealtime, int timestampBase,
+                                         int mirrorMode) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
                             format, dataSpace, rotation,
@@ -171,6 +178,7 @@
         mTimestampOffset(timestampOffset),
         mConsumerUsage(consumerUsage),
         mDropBuffers(false),
+        mMirrorMode(mirrorMode),
         mDequeueBufferLatency(kDequeueLatencyBinSize) {
 
     bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
@@ -379,7 +387,7 @@
                 return res;
             }
         } else {
-            setTransform(transform);
+            setTransform(transform, true/*mayChangeMirror*/);
             res = native_window_set_buffers_timestamp(mConsumer.get(), t);
             if (res != OK) {
                 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
@@ -426,9 +434,15 @@
         "      DequeueBuffer latency histogram:");
 }
 
-status_t Camera3OutputStream::setTransform(int transform) {
+status_t Camera3OutputStream::setTransform(int transform, bool mayChangeMirror) {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
+    if (mMirrorMode != OutputConfiguration::MIRROR_MODE_AUTO && mayChangeMirror) {
+        // If the mirroring mode is not AUTO, do not allow transform update
+        // which may change mirror.
+        return OK;
+    }
+
     return setTransformLocked(transform);
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index c7910b7..80901d6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -93,7 +93,8 @@
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
             bool deviceTimeBaseIsRealtime = false,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
     /**
      * Set up a stream for formats that have a variable buffer size for the same
      * dimensions, such as compressed JPEG.
@@ -109,7 +110,8 @@
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
             bool deviceTimeBaseIsRealtime = false,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
     /**
      * Set up a stream with deferred consumer for formats that have 2 dimensions, such as
      * RAW and YUV. The consumer must be set before using this stream for output. A valid
@@ -124,7 +126,8 @@
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
             bool deviceTimeBaseIsRealtime = false,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
 
     virtual ~Camera3OutputStream();
 
@@ -138,7 +141,7 @@
      * Set the transform on the output stream; one of the
      * HAL_TRANSFORM_* / NATIVE_WINDOW_TRANSFORM_* constants.
      */
-    status_t         setTransform(int transform);
+    status_t         setTransform(int transform, bool mayChangeMirror);
 
     /**
      * Return if this output stream is for video encoding.
@@ -255,7 +258,8 @@
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
             bool deviceTimeBaseIsRealtime = false,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
 
     /**
      * Note that we release the lock briefly in this function
@@ -343,6 +347,8 @@
     std::vector<Surface::BatchBuffer> mBatchedBuffers;
     // ---- End of mBatchLock protected scope ----
 
+    const int mMirrorMode;
+
     /**
      * Internal Camera3Stream interface
      */
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 49f9f62..e44e795 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -34,7 +34,7 @@
      * Set the transform on the output stream; one of the
      * HAL_TRANSFORM_* / NATIVE_WINDOW_TRANSFORM_* constants.
      */
-    virtual status_t setTransform(int transform) = 0;
+    virtual status_t setTransform(int transform, bool mayChangeMirror) = 0;
 
     /**
      * Return if this output stream is for video encoding.
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index d8cc685..ab25322 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -532,7 +532,7 @@
                     auto orientation = deviceInfo->second.find(ANDROID_SENSOR_ORIENTATION);
                     if (orientation.count > 0) {
                         ret = CameraUtils::getRotationTransform(deviceInfo->second,
-                                &request.transform);
+                                OutputConfiguration::MIRROR_MODE_AUTO, &request.transform);
                         if (ret != OK) {
                             ALOGE("%s: Failed to calculate current stream transformation: %s (%d)",
                                     __FUNCTION__, strerror(-ret), ret);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
index 7dc8e10..2e05dda 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
@@ -60,12 +60,12 @@
 }
 
 inline void readBufferFromVec(std::vector<uint8_t> &dst, const std::vector<uint8_t> &src) {
-    // TODO: Check if we're really supposed to copy
     dst = src;
 }
+
 // Reading one camera metadata from result argument via fmq or from the result
 // Assuming the fmq is protected by a lock already
-template <class FmqType, class MetadataType>
+template <class FmqType, class FmqPayloadType, class MetadataType>
 status_t readOneCameraMetadataLockedT(
         std::unique_ptr<FmqType>& fmq,
         uint64_t fmqResultSize,
@@ -76,7 +76,7 @@
         if (fmq == nullptr) {
             return NO_MEMORY; // logged in initialize()
         }
-        if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
+        if (!fmq->read(reinterpret_cast<FmqPayloadType *>(resultMetadata.data()), fmqResultSize)) {
             ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
                     __FUNCTION__, fmqResultSize);
             return INVALID_OPERATION;
@@ -130,8 +130,21 @@
     return handle.fds[0].get();
 }
 
+inline const hardware::hidl_vec<uint8_t>&
+getResultMetadata(const android::hardware::camera::device::V3_2::CameraMetadata &result) {
+    return result;
+}
+
+inline const std::vector<uint8_t>&
+getResultMetadata(const aidl::android::hardware::camera::device::CameraMetadata &result) {
+    return result.metadata;
+}
+
+// Fmqpayload type is needed since AIDL generates an fmq of payload type int8_t
+// for a byte fmq vs MetadataType which is uint8_t. For HIDL, the same type is
+// generated for metadata and fmq payload : uint8_t.
 template <class StatesType, class CaptureResultType, class PhysMetadataType, class MetadataType,
-        class FmqType, class BufferStatusType>
+         class FmqType, class BufferStatusType, class FmqPayloadType = uint8_t>
 void processOneCaptureResultLockedT(
         StatesType& states,
         const CaptureResultType& result,
@@ -144,9 +157,9 @@
 
     // Read and validate the result metadata.
     MetadataType resultMetadata;
-    res = readOneCameraMetadataLockedT(
+    res = readOneCameraMetadataLockedT<FmqType, FmqPayloadType, MetadataType>(
             fmq, result.fmqResultSize,
-            resultMetadata, result.result);
+            resultMetadata, getResultMetadata(result.result));
     if (res != OK) {
         ALOGE("%s: Frame %d: Failed to read capture result metadata",
                 __FUNCTION__, result.frameNumber);
@@ -161,8 +174,9 @@
     std::vector<MetadataType> physResultMetadata;
     physResultMetadata.resize(physResultCount);
     for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
-        res = readOneCameraMetadataLockedT(fmq, physicalCameraMetadata[i].fmqMetadataSize,
-                physResultMetadata[i], physicalCameraMetadata[i].metadata);
+        res = readOneCameraMetadataLockedT<FmqType, FmqPayloadType, MetadataType>(fmq,
+                physicalCameraMetadata[i].fmqMetadataSize,
+                physResultMetadata[i], getResultMetadata(physicalCameraMetadata[i].metadata));
         if (res != OK) {
             ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
                     __FUNCTION__, result.frameNumber,
@@ -170,8 +184,8 @@
             return;
         }
         physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
-        phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
-                physResultMetadata[i].data());
+        phyCamMetadatas[i] =
+                reinterpret_cast<const camera_metadata_t*>(physResultMetadata[i].data());
     }
     r.num_physcam_metadata = physResultCount;
     r.physcam_ids = physCamIds.data();
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 047897e..9bf7b6a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -34,11 +34,13 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool useHalBufManager, int dynamicProfile,
-        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
+        int mirrorMode) :
         Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
                             format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
                             consumerUsage, timestampOffset, setId, /*isMultiResolution*/false,
-                            dynamicProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase),
+                            dynamicProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase,
+                            mirrorMode),
         mUseHalBufManager(useHalBufManager) {
     size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
     if (surfaces.size() > consumerCount) {
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index dc22c42..0061a52 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -44,7 +44,8 @@
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
             int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
             bool deviceTimeBaseIsRealtime = false,
-            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT,
+            int mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO);
 
     virtual ~Camera3SharedOutputStream();
 
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 8962fac..148e511 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -113,19 +113,21 @@
         int dynamicRangeProfile;
         int streamUseCase;
         int timestampBase;
+        int mirrorMode;
         OutputStreamInfo() :
             width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
             consumerUsage(0),
             dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
             streamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
-            timestampBase(OutputConfiguration::TIMESTAMP_BASE_DEFAULT) {}
+            timestampBase(OutputConfiguration::TIMESTAMP_BASE_DEFAULT),
+            mirrorMode(OutputConfiguration::MIRROR_MODE_AUTO) {}
         OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
                 uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed,
-                int _dynamicRangeProfile, int _streamUseCase, int _timestampBase) :
+                int _dynamicRangeProfile, int _streamUseCase, int _timestampBase, int _mirrorMode) :
             width(_width), height(_height), format(_format),
             dataSpace(_dataSpace), consumerUsage(_consumerUsage),
             sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile),
-            streamUseCase(_streamUseCase), timestampBase(_timestampBase) {}
+            streamUseCase(_streamUseCase), timestampBase(_timestampBase), mirrorMode(_mirrorMode) {}
 };
 
 /**
diff --git a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
index 6135f9e..154e6f5 100644
--- a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
+++ b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
@@ -187,7 +187,7 @@
 
 status_t PreviewFrameScheduler::queueBufferToClientLocked(
         const BufferHolder& bufferHolder, nsecs_t timestamp) {
-    mParent.setTransform(bufferHolder.transform);
+    mParent.setTransform(bufferHolder.transform, true/*mayChangeMirror*/);
 
     status_t res = native_window_set_buffers_timestamp(mConsumer.get(), timestamp);
     if (res != OK) {
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
new file mode 100644
index 0000000..9ace0f9
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -0,0 +1,1580 @@
+/*
+ * 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 "AidlCamera3-Device"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+            ##__VA_ARGS__)
+
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+            ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState(   \
+    "%s: " fmt, __FUNCTION__,              \
+    ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+    "%s: " fmt, __FUNCTION__,                    \
+    ##__VA_ARGS__)
+
+#include <inttypes.h>
+
+#include <utility>
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <utils/Timers.h>
+#include <cutils/properties.h>
+
+#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+
+#include "utils/CameraTraces.h"
+#include "mediautils/SchedulingPolicyService.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3FakeStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "device3/aidl/AidlCamera3OutputUtils.h"
+#include "device3/aidl/AidlCamera3OfflineSession.h"
+#include "CameraService.h"
+#include "utils/CameraThreadState.h"
+#include "utils/SessionConfigurationUtils.h"
+#include "utils/TraceHFR.h"
+#include "utils/CameraServiceProxyWrapper.h"
+
+#include "../../common/aidl/AidlProviderInfo.h"
+
+#include <algorithm>
+
+#include "AidlCamera3Device.h"
+
+using namespace android::camera3;
+using namespace aidl::android::hardware;
+using aidl::android::hardware::camera::metadata::SensorPixelMode;
+using aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
+using aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
+
+namespace android {
+
+RequestAvailableDynamicRangeProfilesMap
+mapToAidlDynamicProfile(int dynamicRangeProfile) {
+    return static_cast<RequestAvailableDynamicRangeProfilesMap>(dynamicRangeProfile);
+}
+
+aidl::android::hardware::graphics::common::PixelFormat AidlCamera3Device::mapToAidlPixelFormat(
+        int frameworkFormat) {
+    return (aidl::android::hardware::graphics::common::PixelFormat) frameworkFormat;
+}
+
+aidl::android::hardware::graphics::common::Dataspace AidlCamera3Device::mapToAidlDataspace(
+        android_dataspace dataSpace) {
+    return (aidl::android::hardware::graphics::common::Dataspace)dataSpace;
+}
+
+aidl::android::hardware::graphics::common::BufferUsage AidlCamera3Device::mapToAidlConsumerUsage(
+        uint64_t usage) {
+    return (aidl::android::hardware::graphics::common::BufferUsage)usage;
+}
+
+aidl::android::hardware::camera::device::StreamRotation
+AidlCamera3Device::mapToAidlStreamRotation(camera_stream_rotation_t rotation) {
+    switch (rotation) {
+        case CAMERA_STREAM_ROTATION_0:
+            return aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
+        case CAMERA_STREAM_ROTATION_90:
+            return aidl::android::hardware::camera::device::StreamRotation::ROTATION_90;
+        case CAMERA_STREAM_ROTATION_180:
+            return aidl::android::hardware::camera::device::StreamRotation::ROTATION_180;
+        case CAMERA_STREAM_ROTATION_270:
+            return aidl::android::hardware::camera::device::StreamRotation::ROTATION_270;
+    }
+    ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
+    return aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
+}
+
+status_t AidlCamera3Device::mapToAidlStreamConfigurationMode(
+        camera_stream_configuration_mode_t operationMode,
+        aidl::android::hardware::camera::device::StreamConfigurationMode *mode) {
+    using StreamConfigurationMode =
+            aidl::android::hardware::camera::device::StreamConfigurationMode;
+    if (mode == nullptr) return BAD_VALUE;
+    if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+        switch(operationMode) {
+            case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
+                *mode = StreamConfigurationMode::NORMAL_MODE;
+                break;
+            case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+                *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
+                break;
+            default:
+                ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
+                return BAD_VALUE;
+        }
+    } else {
+        *mode = static_cast<StreamConfigurationMode>(operationMode);
+    }
+    return OK;
+}
+
+int AidlCamera3Device::mapToFrameworkFormat(
+        aidl::android::hardware::graphics::common::PixelFormat pixelFormat) {
+    return static_cast<uint32_t>(pixelFormat);
+}
+
+android_dataspace AidlCamera3Device::mapToFrameworkDataspace(
+        aidl::android::hardware::graphics::common::Dataspace dataSpace) {
+    return static_cast<android_dataspace>(dataSpace);
+}
+
+uint64_t AidlCamera3Device::mapConsumerToFrameworkUsage(
+        aidl::android::hardware::graphics::common::BufferUsage usage) {
+    return (uint64_t)usage;
+}
+
+uint64_t AidlCamera3Device::mapProducerToFrameworkUsage(
+       aidl::android::hardware::graphics::common::BufferUsage usage) {
+    return (uint64_t)usage;
+}
+
+AidlCamera3Device::AidlCamera3Device(const String8& id, bool overrideForPerfClass,
+            bool legacyClient) : Camera3Device(id, overrideForPerfClass, legacyClient) {
+        mCallbacks = ndk::SharedRefBase::make<AidlCameraDeviceCallbacks>(this);
+}
+
+status_t AidlCamera3Device::initialize(sp<CameraProviderManager> manager,
+        const String8& monitorTags) {
+    ATRACE_CALL();
+    Mutex::Autolock il(mInterfaceLock);
+    Mutex::Autolock l(mLock);
+
+    ALOGV("%s: Initializing AIDL device for camera %s", __FUNCTION__, mId.string());
+    if (mStatus != STATUS_UNINITIALIZED) {
+        CLOGE("Already initialized!");
+        return INVALID_OPERATION;
+    }
+    if (manager == nullptr) return INVALID_OPERATION;
+
+    std::shared_ptr<camera::device::ICameraDeviceSession> session;
+    ATRACE_BEGIN("CameraHal::openSession");
+    status_t res = manager->openAidlSession(mId.string(), mCallbacks,
+            /*out*/ &session);
+    ATRACE_END();
+    if (res != OK) {
+        SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
+        return res;
+    }
+    if (session == nullptr) {
+      ALOGE("JCLog: null session returned");
+      SET_ERR("Session iface returned is null");
+      return INVALID_OPERATION;
+    }
+    res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo);
+    if (res != OK) {
+        SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
+        session->close();
+        return res;
+    }
+    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
+
+    std::vector<std::string> physicalCameraIds;
+    bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
+    if (isLogical) {
+        for (auto& physicalId : physicalCameraIds) {
+            // Do not override characteristics for physical cameras
+            res = manager->getCameraCharacteristics(
+                    physicalId, /*overrideForPerfClass*/false, &mPhysicalDeviceInfoMap[physicalId]);
+            if (res != OK) {
+                SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
+                        physicalId.c_str(), strerror(-res), res);
+                session->close();
+                return res;
+            }
+
+            bool usePrecorrectArray =
+                    DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
+            if (usePrecorrectArray) {
+                res = mDistortionMappers[physicalId].setupStaticInfo(
+                        mPhysicalDeviceInfoMap[physicalId]);
+                if (res != OK) {
+                    SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
+                            "correction", physicalId.c_str());
+                    session->close();
+                    return res;
+                }
+            }
+
+            mZoomRatioMappers[physicalId] = ZoomRatioMapper(
+                    &mPhysicalDeviceInfoMap[physicalId],
+                    mSupportNativeZoomRatio, usePrecorrectArray);
+
+            if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+                    mPhysicalDeviceInfoMap[physicalId])) {
+                mUHRCropAndMeteringRegionMappers[physicalId] =
+                        UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
+                                usePrecorrectArray);
+            }
+        }
+    }
+
+    std::shared_ptr<AidlRequestMetadataQueue> queue;
+    ::aidl::android::hardware::common::fmq::MQDescriptor<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> desc;
+
+    ::ndk::ScopedAStatus requestQueueRet = session->getCaptureRequestMetadataQueue(&desc);
+    if (!requestQueueRet.isOk()) {
+        ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+                requestQueueRet.getMessage());
+        return AidlProviderInfo::mapToStatusT(requestQueueRet);
+    }
+    queue = std::make_unique<AidlRequestMetadataQueue>(desc);
+    if (!queue->isValid() || queue->availableToWrite() <= 0) {
+        ALOGE("HAL returns empty result metadata fmq, not use it");
+        queue = nullptr;
+        // Don't use resQueue onwards.
+    }
+
+    std::unique_ptr<AidlResultMetadataQueue>& resQueue = mResultMetadataQueue;
+    ::aidl::android::hardware::common::fmq::MQDescriptor<
+        int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> resDesc;
+    ::ndk::ScopedAStatus resultQueueRet = session->getCaptureResultMetadataQueue(&resDesc);
+    if (!resultQueueRet.isOk()) {
+        ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+                resultQueueRet.getMessage());
+        return AidlProviderInfo::mapToStatusT(resultQueueRet);
+    }
+    resQueue = std::make_unique<AidlResultMetadataQueue>(resDesc);
+    if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+        ALOGE("HAL returns empty result metadata fmq, not use it");
+        resQueue = nullptr;
+        // Don't use resQueue onwards.
+    }
+
+    camera_metadata_entry bufMgrMode =
+            mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+    if (bufMgrMode.count > 0) {
+        mUseHalBufManager = (bufMgrMode.data.u8[0] ==
+                ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+    }
+
+    camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    for (size_t i = 0; i < capabilities.count; i++) {
+        uint8_t capability = capabilities.data.u8[i];
+        if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
+            mSupportOfflineProcessing = true;
+        }
+    }
+
+    mInterface = new AidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
+
+    std::string providerType;
+    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
+    mTagMonitor.initialize(mVendorTagId);
+    if (!monitorTags.isEmpty()) {
+        mTagMonitor.parseTagsToMonitor(String8(monitorTags));
+    }
+
+    for (size_t i = 0; i < capabilities.count; i++) {
+        uint8_t capability = capabilities.data.u8[i];
+        if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
+            mNeedFixupMonochromeTags = true;
+        }
+    }
+
+    return initializeCommonLocked();
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::AidlCameraDeviceCallbacks::processCaptureResult(
+            const std::vector<camera::device::CaptureResult>& results) {
+    sp<AidlCamera3Device> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->processCaptureResult(results);
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::AidlCameraDeviceCallbacks::notify(
+        const std::vector<camera::device::NotifyMsg>& msgs) {
+    sp<AidlCamera3Device> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->notify(msgs);
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::processCaptureResult(
+            const std::vector<camera::device::CaptureResult>& results) {
+    // Ideally we should grab mLock, but that can lead to deadlock, and
+    // it's not super important to get up to date value of mStatus for this
+    // warning print, hence skipping the lock here
+    if (mStatus == STATUS_ERROR) {
+        // Per API contract, HAL should act as closed after device error
+        // But mStatus can be set to error by framework as well, so just log
+        // a warning here.
+        ALOGW("%s: received capture result in error state.", __FUNCTION__);
+    }
+
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> l(mOutputLock);
+        listener = mListener.promote();
+    }
+
+    if (mProcessCaptureResultLock.tryLock() != OK) {
+        // This should never happen; it indicates a wrong client implementation
+        // that doesn't follow the contract. But, we can be tolerant here.
+        ALOGE("%s: callback overlapped! waiting 1s...",
+                __FUNCTION__);
+        if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+            ALOGE("%s: cannot acquire lock in 1s, dropping results",
+                    __FUNCTION__);
+            // really don't know what to do, so bail out.
+            return ::ndk::ScopedAStatus::ok();
+        }
+    }
+    AidlCaptureOutputStates states {
+       {
+        mId,
+        mInFlightLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
+        *this, *(mInterface), mLegacyClient}, mResultMetadataQueue
+    };
+
+    for (const auto& result : results) {
+        processOneCaptureResultLocked(states, result, result.physicalCameraMetadata);
+    }
+    mProcessCaptureResultLock.unlock();
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::notify(
+        const std::vector<camera::device::NotifyMsg>& msgs) {
+    // Ideally we should grab mLock, but that can lead to deadlock, and
+    // it's not super important to get up to date value of mStatus for this
+    // warning print, hence skipping the lock here
+    if (mStatus == STATUS_ERROR) {
+        // Per API contract, HAL should act as closed after device error
+        // But mStatus can be set to error by framework as well, so just log
+        // a warning here.
+        ALOGW("%s: received notify message in error state.", __FUNCTION__);
+    }
+
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> l(mOutputLock);
+        listener = mListener.promote();
+    }
+
+    AidlCaptureOutputStates states {
+      { mId,
+        mInFlightLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
+        *this, *(mInterface), mLegacyClient}, mResultMetadataQueue
+    };
+    for (const auto& msg : msgs) {
+        camera3::notify(states, msg);
+    }
+    return ::ndk::ScopedAStatus::ok();
+
+}
+
+status_t AidlCamera3Device::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/ sp<CameraOfflineSessionBase>* session) {
+    ATRACE_CALL();
+    if (session == nullptr) {
+        ALOGE("%s: session must not be null", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock il(mInterfaceLock);
+
+    bool hasInputStream = mInputStream != nullptr;
+    int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
+    bool inputStreamSupportsOffline = hasInputStream ?
+            mInputStream->getOfflineProcessingSupport() : false;
+    auto outputStreamIds = mOutputStreams.getStreamIds();
+    auto streamIds = outputStreamIds;
+    if (hasInputStream) {
+        streamIds.push_back(mInputStream->getId());
+    }
+
+    // Check all streams in streamsToKeep supports offline mode
+    for (auto id : streamsToKeep) {
+        if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+            ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
+            return BAD_VALUE;
+        } else if (id == inputStreamId) {
+            if (!inputStreamSupportsOffline) {
+                ALOGE("%s: input stream %d cannot be switched to offline",
+                        __FUNCTION__, id);
+                return BAD_VALUE;
+            }
+        } else {
+            sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
+            if (!stream->getOfflineProcessingSupport()) {
+                ALOGE("%s: output stream %d cannot be switched to offline",
+                        __FUNCTION__, id);
+                return BAD_VALUE;
+            }
+        }
+    }
+    // TODO: block surface sharing and surface group streams until we can support them
+
+    // Stop repeating request, wait until all remaining requests are submitted, then call into
+    // HAL switchToOffline
+    camera::device::CameraOfflineSessionInfo offlineSessionInfo;
+    std::shared_ptr<camera::device::ICameraOfflineSession> offlineSession;
+    camera3::BufferRecords bufferRecords;
+    status_t ret = static_cast<AidlRequestThread *>(mRequestThread.get())->switchToOffline(
+            streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
+
+    if (ret != OK) {
+        SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
+        return ret;
+    }
+
+    bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
+    if (!succ) {
+        SET_ERR("HAL must not be calling requestStreamBuffers call");
+        // TODO: block ALL callbacks from HAL till app configured new streams?
+        return UNKNOWN_ERROR;
+    }
+
+    // Verify offlineSessionInfo
+    std::vector<int32_t> offlineStreamIds;
+    offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        // verify stream IDs
+        int32_t id = offlineStream.id;
+        if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+            SET_ERR("stream ID %d not found!", id);
+            return UNKNOWN_ERROR;
+        }
+
+        // When not using HAL buf manager, only allow streams requested by app to be preserved
+        if (!mUseHalBufManager) {
+            if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
+                SET_ERR("stream ID %d must not be switched to offline!", id);
+                return UNKNOWN_ERROR;
+            }
+        }
+
+        offlineStreamIds.push_back(id);
+        sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
+                static_cast<sp<Camera3StreamInterface>>(mInputStream) :
+                static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
+        // Verify number of outstanding buffers
+        if (stream->getOutstandingBuffersCount() != (uint32_t)offlineStream.numOutstandingBuffers) {
+            SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
+                    id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    // Verify all streams to be deleted don't have any outstanding buffers
+    if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+                inputStreamId) == offlineStreamIds.end()) {
+        if (mInputStream->hasOutstandingBuffers()) {
+            SET_ERR("Input stream %d still has %zu outstanding buffer!",
+                    inputStreamId, mInputStream->getOutstandingBuffersCount());
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    for (const auto& outStreamId : outputStreamIds) {
+        if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+                outStreamId) == offlineStreamIds.end()) {
+            auto outStream = mOutputStreams.get(outStreamId);
+            if (outStream->hasOutstandingBuffers()) {
+                SET_ERR("Output stream %d still has %zu outstanding buffer!",
+                        outStreamId, outStream->getOutstandingBuffersCount());
+                return UNKNOWN_ERROR;
+            }
+        }
+    }
+
+    InFlightRequestMap offlineReqs;
+    // Verify inflight requests and their pending buffers
+    {
+        std::lock_guard<std::mutex> l(mInFlightLock);
+        for (auto offlineReq : offlineSessionInfo.offlineRequests) {
+            int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
+            if (idx == NAME_NOT_FOUND) {
+                SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
+                return UNKNOWN_ERROR;
+            }
+
+            const auto& inflightReq = mInFlightMap.valueAt(idx);
+            // TODO: check specific stream IDs
+            size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
+            if (numBuffersLeft != offlineReq.pendingStreams.size()) {
+                SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
+                        inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
+                return UNKNOWN_ERROR;
+            }
+            offlineReqs.add(offlineReq.frameNumber, inflightReq);
+        }
+    }
+
+    // Create Camera3OfflineSession and transfer object ownership
+    //   (streams, inflight requests, buffer caches)
+    camera3::StreamSet offlineStreamSet;
+    sp<camera3::Camera3Stream> inputStream;
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        int32_t id = offlineStream.id;
+        if (mInputStream != nullptr && id == mInputStream->getId()) {
+            inputStream = mInputStream;
+        } else {
+            offlineStreamSet.add(id, mOutputStreams.get(id));
+        }
+    }
+
+    // TODO: check if we need to lock before copying states
+    //       though technically no other thread should be talking to Camera3Device at this point
+    Camera3OfflineStates offlineStates(
+            mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
+            mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
+            mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+            mNextResultFrameNumber, mNextReprocessResultFrameNumber,
+            mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
+            mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+            mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
+            mZoomRatioMappers, mRotateAndCropMappers);
+
+    *session = new AidlCamera3OfflineSession(mId, inputStream, offlineStreamSet,
+            std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
+
+    // Delete all streams that has been transferred to offline session
+    Mutex::Autolock l(mLock);
+    for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+        int32_t id = offlineStream.id;
+        if (mInputStream != nullptr && id == mInputStream->getId()) {
+            mInputStream.clear();
+        } else {
+            mOutputStreams.remove(id);
+        }
+    }
+
+    // disconnect all other streams and switch to UNCONFIGURED state
+    if (mInputStream != nullptr) {
+        ret = mInputStream->disconnect();
+        if (ret != OK) {
+            SET_ERR_L("disconnect input stream failed!");
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    for (auto streamId : mOutputStreams.getStreamIds()) {
+        sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
+        ret = stream->disconnect();
+        if (ret != OK) {
+            SET_ERR_L("disconnect output stream %d failed!", streamId);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    mInputStream.clear();
+    mOutputStreams.clear();
+    mNeedConfig = true;
+    internalUpdateStatusLocked(STATUS_UNCONFIGURED);
+    mOperatingMode = NO_MODE;
+    mIsConstrainedHighSpeedConfiguration = false;
+    mRequestThread->clearPreviousRequest();
+
+    return OK;
+    // TO be done by CameraDeviceClient/Camera3OfflineSession
+    // register the offline client to camera service
+    // Setup result passthing threads etc
+    // Initialize offline session so HAL can start sending callback to it (result Fmq)
+    // TODO: check how many onIdle callback will be sent
+    // Java side to make sure the CameraCaptureSession is properly closed
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::AidlCameraDeviceCallbacks::requestStreamBuffers(
+        const std::vector<camera::device::BufferRequest>& bufReqs,
+        std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+        aidl::android::hardware::camera::device::BufferRequestStatus* status) {
+
+    sp<AidlCamera3Device> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->requestStreamBuffers(bufReqs, outBuffers, status);
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::requestStreamBuffers(
+        const std::vector<camera::device::BufferRequest>& bufReqs,
+        std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+        aidl::android::hardware::camera::device::BufferRequestStatus* status) {
+
+    RequestBufferStates states {
+        mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
+        mSessionStatsBuilder, *this, *(mInterface), *this};
+    camera3::requestStreamBuffers(states, bufReqs, outBuffers, status);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::AidlCameraDeviceCallbacks::returnStreamBuffers(
+        const std::vector<camera::device::StreamBuffer>& buffers) {
+    sp<AidlCamera3Device> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->returnStreamBuffers(buffers);
+}
+
+::ndk::ScopedAStatus AidlCamera3Device::returnStreamBuffers(
+        const std::vector<camera::device::StreamBuffer>& buffers) {
+    ReturnBufferStates states {
+        mId, mUseHalBufManager, mOutputStreams,  mSessionStatsBuilder,
+        *(mInterface)};
+    camera3::returnStreamBuffers(states, buffers);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+AidlCamera3Device::AidlHalInterface::AidlHalInterface(
+            std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession> &session,
+            std::shared_ptr<AidlRequestMetadataQueue> queue,
+            bool useHalBufManager, bool supportOfflineProcessing) :
+        HalInterface(useHalBufManager, supportOfflineProcessing),
+        mAidlSession(session),
+        mRequestMetadataQueue(queue) { }
+
+AidlCamera3Device::AidlHalInterface::AidlHalInterface(
+            std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession>
+                    &deviceSession,
+            std::shared_ptr<aidl::android::hardware::camera::device::ICameraInjectionSession>
+                    &injectionSession, std::shared_ptr<AidlRequestMetadataQueue> queue,
+            bool useHalBufManager, bool supportOfflineProcessing) :
+        HalInterface(useHalBufManager, supportOfflineProcessing),
+        mAidlSession(deviceSession),
+        mAidlInjectionSession(injectionSession),
+        mRequestMetadataQueue(queue) { }
+
+bool AidlCamera3Device::AidlHalInterface::valid() {
+    return (mAidlSession != nullptr);
+}
+
+void AidlCamera3Device::AidlHalInterface::clear() {
+    mAidlSession.reset();
+}
+
+status_t AidlCamera3Device::AidlHalInterface::flush() {
+    ATRACE_NAME("CameraHal::flush");
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    auto err = mAidlSession->flush();
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        res = AidlProviderInfo::mapToStatusT(err);
+    }
+
+    return res;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::dump(int /*fd*/) {
+    ATRACE_NAME("CameraHal::dump");
+    if (!valid()) return INVALID_OPERATION;
+
+    // Handled by CameraProviderManager::dump
+
+    return OK;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::repeatingRequestEnd(uint32_t frameNumber,
+        const std::vector<int32_t> &streamIds) {
+    ATRACE_NAME("AidlCameraHal::repeatingRequestEnd");
+    if (!valid()) return INVALID_OPERATION;
+
+    mAidlSession->repeatingRequestEnd(frameNumber, streamIds);
+
+    return OK;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::close() {
+    ATRACE_NAME("CameraHal::close()");
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    auto err = mAidlSession->close();
+    // Interface will be dead shortly anyway, so don't log errors
+    if (!err.isOk()) {
+        res = DEAD_OBJECT;
+    }
+
+    return res;
+}
+
+void AidlCamera3Device::AidlHalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
+    ATRACE_NAME("CameraHal::signalPipelineDrain");
+    if (!valid()) {
+        ALOGE("%s called on invalid camera!", __FUNCTION__);
+        return;
+    }
+
+    auto err = mAidlSession->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        return;
+    }
+}
+
+bool AidlCamera3Device::AidlHalInterface::isReconfigurationRequired(
+        CameraMetadata& oldSessionParams, CameraMetadata& newSessionParams) {
+    // We do reconfiguration by default;
+    bool required = true;
+    if (mIsReconfigurationQuerySupported) {
+        aidl::android::hardware::camera::device::CameraMetadata oldParams, newParams;
+        camera_metadata_t* oldSessionMeta = const_cast<camera_metadata_t*>(
+                oldSessionParams.getAndLock());
+        uint8_t *oldSessionByteP = reinterpret_cast<uint8_t*>(oldSessionMeta);
+
+        camera_metadata_t* newSessionMeta = const_cast<camera_metadata_t*>(
+                newSessionParams.getAndLock());
+        uint8_t *newSessionByteP = reinterpret_cast<uint8_t*>(newSessionMeta);
+        // std::vector has no setToExternal, so we hacve to copy
+        oldParams.metadata.assign(oldSessionByteP,
+                oldSessionByteP + get_camera_metadata_size(oldSessionMeta));
+        newParams.metadata.assign(newSessionByteP,
+                newSessionByteP + get_camera_metadata_size(newSessionMeta));
+        auto err = mAidlSession->isReconfigurationRequired(oldParams, newParams, &required);
+        oldSessionParams.unlock(oldSessionMeta);
+        newSessionParams.unlock(newSessionMeta);
+        if (!err.isOk()) {
+            ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.getMessage());
+            return true;
+        }
+    }
+
+    return required;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::constructDefaultRequestSettings(
+        camera_request_template_t templateId,
+        /*out*/ camera_metadata_t **requestTemplate) {
+    ATRACE_NAME("CameraAidlHal::constructDefaultRequestSettings");
+    using aidl::android::hardware::camera::device::RequestTemplate;
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    RequestTemplate id;
+    aidl::android::hardware::camera::device::CameraMetadata request;
+    switch (templateId) {
+        case CAMERA_TEMPLATE_PREVIEW:
+            id = RequestTemplate::PREVIEW;
+            break;
+        case CAMERA_TEMPLATE_STILL_CAPTURE:
+            id = RequestTemplate::STILL_CAPTURE;
+            break;
+        case CAMERA_TEMPLATE_VIDEO_RECORD:
+            id = RequestTemplate::VIDEO_RECORD;
+            break;
+        case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
+            id = RequestTemplate::VIDEO_SNAPSHOT;
+            break;
+        case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
+            id = RequestTemplate::ZERO_SHUTTER_LAG;
+            break;
+        case CAMERA_TEMPLATE_MANUAL:
+            id = RequestTemplate::MANUAL;
+            break;
+        default:
+            // Unknown template ID, or this HAL is too old to support it
+            return BAD_VALUE;
+    }
+    auto err = mAidlSession->constructDefaultRequestSettings(id, &request);
+
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        return AidlProviderInfo::mapToStatusT(err);
+    }
+    const camera_metadata *r =
+            reinterpret_cast<const camera_metadata_t*>(request.metadata.data());
+    size_t expectedSize = request.metadata.size();
+    int ret = validate_camera_metadata_structure(r, &expectedSize);
+    if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+        *requestTemplate = clone_camera_metadata(r);
+        if (*requestTemplate == nullptr) {
+            ALOGE("%s: Unable to clone camera metadata received from HAL",
+                    __FUNCTION__);
+            res = UNKNOWN_ERROR;
+        }
+    } else {
+        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+        res = UNKNOWN_ERROR;
+    }
+
+    return res;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::configureStreams(
+    const camera_metadata_t *sessionParams,
+        camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
+    using camera::device::StreamType;
+    using camera::device::StreamConfigurationMode;
+
+    ATRACE_NAME("CameraHal::configureStreams");
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    // Convert stream config to AIDL
+    std::set<int> activeStreams;
+    camera::device::StreamConfiguration requestedConfiguration;
+    requestedConfiguration.streams.resize(config->num_streams);
+    for (size_t i = 0; i < config->num_streams; i++) {
+        camera::device::Stream &dst = requestedConfiguration.streams[i];
+        camera3::camera_stream_t *src = config->streams[i];
+
+        Camera3Stream* cam3stream = Camera3Stream::cast(src);
+        cam3stream->setBufferFreedListener(this);
+        int streamId = cam3stream->getId();
+        StreamType streamType;
+        switch (src->stream_type) {
+            case CAMERA_STREAM_OUTPUT:
+                streamType = StreamType::OUTPUT;
+                break;
+            case CAMERA_STREAM_INPUT:
+                streamType = StreamType::INPUT;
+                break;
+            default:
+                ALOGE("%s: Stream %d: Unsupported stream type %d",
+                        __FUNCTION__, streamId, config->streams[i]->stream_type);
+                return BAD_VALUE;
+        }
+        dst.id = streamId;
+        dst.streamType = streamType;
+        dst.width = src->width;
+        dst.height = src->height;
+        dst.usage = mapToAidlConsumerUsage(cam3stream->getUsage());
+        dst.rotation = mapToAidlStreamRotation((camera_stream_rotation_t) src->rotation);
+        dst.format = mapToAidlPixelFormat(cam3stream->isFormatOverridden() ?
+                    cam3stream->getOriginalFormat() : src->format);
+        dst.dataSpace = mapToAidlDataspace(cam3stream->isDataSpaceOverridden() ?
+                    cam3stream->getOriginalDataSpace() : src->data_space);
+
+        dst.bufferSize = bufferSizes[i];
+        if (src->physical_camera_id != nullptr) {
+            dst.physicalCameraId = src->physical_camera_id;
+        }
+        dst.groupId = cam3stream->getHalStreamGroupId();
+        dst.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+        size_t j = 0;
+        for (int mode : src->sensor_pixel_modes_used) {
+            dst.sensorPixelModesUsed[j++] = static_cast<SensorPixelMode>(mode);
+        }
+        dst.dynamicRangeProfile = mapToAidlDynamicProfile(src->dynamic_range_profile);
+        dst.useCase = static_cast<ScalerAvailableStreamUseCases>(src->use_case);
+        activeStreams.insert(streamId);
+        // Create Buffer ID map if necessary
+        mBufferRecords.tryCreateBufferCache(streamId);
+    }
+    // remove BufferIdMap for deleted streams
+    mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+    StreamConfigurationMode operationMode;
+    res = mapToAidlStreamConfigurationMode(
+            (camera_stream_configuration_mode_t) config->operation_mode,
+            /*out*/ &operationMode);
+    if (res != OK) {
+        return res;
+    }
+    requestedConfiguration.operationMode = operationMode;
+    size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+    uint8_t *sessionParamP =
+            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams));
+
+    // std::vector has no setToExternal, so we have to copy
+    requestedConfiguration.sessionParams.metadata.assign(
+                sessionParamP, sessionParamP + sessionParamSize);
+    requestedConfiguration.operationMode = operationMode;
+
+    // Invoke configureStreams
+    std::vector<camera::device::HalStream> finalConfiguration;
+
+    requestedConfiguration.streamConfigCounter = mNextStreamConfigCounter++;
+    requestedConfiguration.multiResolutionInputImage = config->input_is_multi_resolution;
+    auto err = mAidlSession->configureStreams(requestedConfiguration, &finalConfiguration);
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        return AidlProviderInfo::mapToStatusT(err);
+    }
+
+    // And convert output stream configuration from AIDL
+
+    for (size_t i = 0; i < config->num_streams; i++) {
+        camera3::camera_stream_t *dst = config->streams[i];
+        int streamId = Camera3Stream::cast(dst)->getId();
+
+        // Start scan at i, with the assumption that the stream order matches
+        size_t realIdx = i;
+        bool found = false;
+        size_t halStreamCount = finalConfiguration.size();
+        for (size_t idx = 0; idx < halStreamCount; idx++) {
+            if (finalConfiguration[realIdx].id == streamId) {
+                found = true;
+                break;
+            }
+            realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
+        }
+        if (!found) {
+            ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+                    __FUNCTION__, streamId);
+            return INVALID_OPERATION;
+        }
+        camera::device::HalStream &src = finalConfiguration[realIdx];
+
+        Camera3Stream* dstStream = Camera3Stream::cast(dst);
+        int overrideFormat = mapToFrameworkFormat(src.overrideFormat);
+        android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
+
+        dstStream->setOfflineProcessingSupport(src.supportOffline);
+
+        if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+            dstStream->setFormatOverride(false);
+            dstStream->setDataSpaceOverride(false);
+            if (dst->format != overrideFormat) {
+                ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
+                        streamId, dst->format);
+            }
+            if (dst->data_space != overrideDataSpace) {
+                ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
+                        streamId, dst->format);
+            }
+        } else {
+            bool needFormatOverride =
+                    requestedConfiguration.streams[i].format != src.overrideFormat;
+            bool needDataspaceOverride =
+                    requestedConfiguration.streams[i].dataSpace != src.overrideDataSpace;
+            // Override allowed with IMPLEMENTATION_DEFINED
+            dstStream->setFormatOverride(needFormatOverride);
+            dstStream->setDataSpaceOverride(needDataspaceOverride);
+            dst->format = overrideFormat;
+            dst->data_space = overrideDataSpace;
+        }
+
+        if (dst->stream_type == CAMERA_STREAM_INPUT) {
+            if (static_cast<int64_t>(src.producerUsage) != 0) {
+                ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
+                        __FUNCTION__, streamId);
+                return INVALID_OPERATION;
+            }
+            dstStream->setUsage(
+                    mapConsumerToFrameworkUsage(src.consumerUsage));
+        } else {
+            // OUTPUT
+            if (static_cast<int64_t>(src.consumerUsage) != 0) {
+                ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
+                        __FUNCTION__, streamId);
+                return INVALID_OPERATION;
+            }
+            dstStream->setUsage(
+                    mapProducerToFrameworkUsage(src.producerUsage));
+        }
+        dst->max_buffers = src.maxBuffers;
+    }
+
+    return res;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::configureInjectedStreams(
+        const camera_metadata_t* sessionParams, camera_stream_configuration* config,
+        const std::vector<uint32_t>& bufferSizes,
+        const CameraMetadata& cameraCharacteristics) {
+    using camera::device::StreamType;
+    using camera::device::StreamConfigurationMode;
+
+    ATRACE_NAME("InjectionCameraHal::configureStreams");
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    if (config->input_is_multi_resolution) {
+        ALOGE("%s: Injection camera device doesn't support multi-resolution input "
+                "stream", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    // Convert stream config to AIDL
+    std::set<int> activeStreams;
+    camera::device::StreamConfiguration requestedConfiguration;
+    requestedConfiguration.streams.resize(config->num_streams);
+    for (size_t i = 0; i < config->num_streams; i++) {
+        camera::device::Stream& dst = requestedConfiguration.streams[i];
+        camera3::camera_stream_t* src = config->streams[i];
+
+        Camera3Stream* cam3stream = Camera3Stream::cast(src);
+        cam3stream->setBufferFreedListener(this);
+        int streamId = cam3stream->getId();
+        StreamType streamType;
+        switch (src->stream_type) {
+            case CAMERA_STREAM_OUTPUT:
+                streamType = StreamType::OUTPUT;
+                break;
+            case CAMERA_STREAM_INPUT:
+                streamType = StreamType::INPUT;
+                break;
+            default:
+                ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
+                        streamId, config->streams[i]->stream_type);
+            return BAD_VALUE;
+        }
+        dst.id = streamId;
+        dst.streamType = streamType;
+        dst.width = src->width;
+        dst.height = src->height;
+        dst.usage = mapToAidlConsumerUsage(cam3stream->getUsage());
+        dst.rotation = mapToAidlStreamRotation((camera_stream_rotation_t)src->rotation);
+        dst.format =
+            mapToAidlPixelFormat(cam3stream->isFormatOverridden() ? cam3stream->getOriginalFormat()
+                    : src->format);
+        dst.dataSpace =
+            mapToAidlDataspace(cam3stream->isDataSpaceOverridden() ?
+                    cam3stream->getOriginalDataSpace() : src->data_space);
+        dst.bufferSize = bufferSizes[i];
+        if (src->physical_camera_id != nullptr) {
+            dst.physicalCameraId = src->physical_camera_id;
+        }
+        dst.groupId = cam3stream->getHalStreamGroupId();
+        dst.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+        size_t j = 0;
+        for (int mode : src->sensor_pixel_modes_used) {
+            dst.sensorPixelModesUsed[j++] = static_cast<SensorPixelMode>(mode);
+        }
+        activeStreams.insert(streamId);
+        // Create Buffer ID map if necessary
+        mBufferRecords.tryCreateBufferCache(streamId);
+    }
+    // remove BufferIdMap for deleted streams
+    mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+    StreamConfigurationMode operationMode;
+    res = mapToAidlStreamConfigurationMode(
+            (camera_stream_configuration_mode_t)config->operation_mode,
+            /*out*/ &operationMode);
+    if (res != OK) {
+        return res;
+    }
+    requestedConfiguration.operationMode = operationMode;
+    size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+    uint8_t *sessionParamP =
+            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams));
+    requestedConfiguration.operationMode = operationMode;
+    requestedConfiguration.sessionParams.metadata.assign(
+            sessionParamP, sessionParamP + sessionParamSize);
+
+    // See which version of HAL we have
+    if (mAidlInjectionSession != nullptr) {
+        requestedConfiguration.streamConfigCounter = mNextStreamConfigCounter++;
+        requestedConfiguration.multiResolutionInputImage = config->input_is_multi_resolution;
+
+        const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
+        uint8_t *aidlCharsP =
+                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata));
+        aidl::android::hardware::camera::device::CameraMetadata aidlChars;
+        aidlChars.metadata.assign(aidlCharsP, aidlCharsP + get_camera_metadata_size(rawMetadata));
+        cameraCharacteristics.unlock(rawMetadata);
+
+        auto err = mAidlInjectionSession->configureInjectionStreams(requestedConfiguration,
+                aidlChars);
+        if (!err.isOk()) {
+            ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+            return AidlProviderInfo::mapToStatusT(err);
+        }
+    } else {
+        ALOGE("%s: mAidlInjectionSession == nullptr, the injection not supported ", __FUNCTION__);
+        return INVALID_OPERATION;
+   }
+
+    return res;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::processBatchCaptureRequests(
+        std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
+    ATRACE_NAME("CameraHal::processBatchCaptureRequests");
+    if (!valid()) return INVALID_OPERATION;
+
+    std::vector<camera::device::CaptureRequest> captureRequests;
+    size_t batchSize = requests.size();
+    if (batchSize > INT_MAX) {
+        ALOGE("%s batchSize %zu > INT_MAX, aidl interface cannot handle batch size", __FUNCTION__,
+                  batchSize);
+        return BAD_VALUE;
+    }
+    captureRequests.resize(batchSize);
+    std::vector<native_handle_t*> handlesCreated;
+    std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
+
+    status_t res = OK;
+    for (size_t i = 0; i < batchSize; i++) {
+       res = wrapAsAidlRequest(requests[i], /*out*/&captureRequests[i],
+                    /*out*/&handlesCreated, /*out*/&inflightBuffers);
+
+        if (res != OK) {
+            mBufferRecords.popInflightBuffers(inflightBuffers);
+            cleanupNativeHandles(&handlesCreated);
+            return res;
+        }
+    }
+
+    std::vector<camera::device::BufferCache> cachesToRemove;
+    {
+        std::lock_guard<std::mutex> lock(mFreedBuffersLock);
+        for (auto& pair : mFreedBuffers) {
+            // The stream might have been removed since onBufferFreed
+            if (mBufferRecords.isStreamCached(pair.first)) {
+                cachesToRemove.push_back({pair.first, static_cast<int64_t>(pair.second)});
+            }
+        }
+        mFreedBuffers.clear();
+    }
+
+    *numRequestProcessed = 0;
+
+    // Write metadata to FMQ.
+    for (size_t i = 0; i < batchSize; i++) {
+        camera_capture_request_t* request = requests[i];
+        camera::device::CaptureRequest* captureRequest;
+        captureRequest = &captureRequests[i];
+
+        if (request->settings != nullptr) {
+            size_t settingsSize = get_camera_metadata_size(request->settings);
+            if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+                    reinterpret_cast<const int8_t*>(request->settings), settingsSize)) {
+                captureRequest->settings.metadata.resize(0);
+                captureRequest->fmqSettingsSize = settingsSize;
+            } else {
+                if (mRequestMetadataQueue != nullptr) {
+                    ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+                }
+                uint8_t *settingsP =
+                        reinterpret_cast<uint8_t*>(
+                                const_cast<camera_metadata_t*>(request->settings));
+                size_t settingsSize =  get_camera_metadata_size(request->settings);
+                captureRequest->settings.metadata.assign(settingsP, settingsP + settingsSize);
+                captureRequest->fmqSettingsSize = 0u;
+            }
+        } else {
+            // A null request settings maps to a size-0 CameraMetadata
+            captureRequest->settings.metadata.resize(0);
+            captureRequest->fmqSettingsSize = 0u;
+        }
+
+        captureRequest ->inputWidth = request->input_width;
+        captureRequest->inputHeight = request->input_height;
+
+        std::vector<camera::device::PhysicalCameraSetting>& physicalCameraSettings =
+                captureRequest->physicalCameraSettings;
+        physicalCameraSettings.resize(request->num_physcam_settings);
+        for (size_t j = 0; j < request->num_physcam_settings; j++) {
+            if (request->physcam_settings != nullptr) {
+                size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+                if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+                            reinterpret_cast<const int8_t*>(request->physcam_settings[j]),
+                            settingsSize)) {
+                    physicalCameraSettings[j].settings.metadata.resize(0);
+                    physicalCameraSettings[j].fmqSettingsSize = settingsSize;
+                } else {
+                    if (mRequestMetadataQueue != nullptr) {
+                        ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+                    }
+                    uint8_t *physicalSettingsP =
+                            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+                                    request->physcam_settings[j]));
+                    physicalCameraSettings[j].settings.metadata.assign(physicalSettingsP,
+                            physicalSettingsP + settingsSize);
+                    physicalCameraSettings[j].fmqSettingsSize = 0u;
+                }
+            } else {
+                physicalCameraSettings[j].fmqSettingsSize = 0u;
+                physicalCameraSettings[j].settings.metadata.resize(0);
+            }
+            physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
+        }
+    }
+
+    int32_t numRequests = 0;
+    auto retS = mAidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+            &numRequests);
+    if (!retS.isOk()) {
+        res = AidlProviderInfo::mapToStatusT(retS);
+    }
+    if (res == OK) {
+        if (numRequests < 0) {
+            res = INVALID_OPERATION;
+        } else {
+            *numRequestProcessed = static_cast<uint32_t>(numRequests);
+        }
+
+    }
+    if (res == OK && *numRequestProcessed == batchSize) {
+        if (mAidlSession->isRemote()) {
+            // Only close acquire fence FDs when the AIDL transaction succeeds (so the FDs have been
+            // sent to camera HAL processes)
+            cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
+        } else {
+            // In passthrough mode the FDs are now owned by HAL
+            cleanupNativeHandles(&handlesCreated);
+        }
+    } else {
+        ALOGE("%s Error with processCaptureRequest %s ", __FUNCTION__, retS.getMessage());
+        mBufferRecords.popInflightBuffers(inflightBuffers);
+        cleanupNativeHandles(&handlesCreated);
+    }
+    return res;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::wrapAsAidlRequest(camera_capture_request_t* request,
+        /*out*/camera::device::CaptureRequest* captureRequest,
+        /*out*/std::vector<native_handle_t*>* handlesCreated,
+        /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
+    using camera::device::BufferStatus;
+    using camera::device::StreamBuffer;
+    ATRACE_CALL();
+    if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
+        ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
+                "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
+        return BAD_VALUE;
+    }
+
+    captureRequest->frameNumber = request->frame_number;
+
+    captureRequest->fmqSettingsSize = 0;
+
+    {
+        if (request->input_buffer != nullptr) {
+            int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
+            buffer_handle_t buf = *(request->input_buffer->buffer);
+            auto pair = getBufferId(buf, streamId);
+            bool isNewBuffer = pair.first;
+            uint64_t bufferId = pair.second;
+            captureRequest->inputBuffer.streamId = streamId;
+            captureRequest->inputBuffer.bufferId = bufferId;
+            captureRequest->inputBuffer.buffer =
+                    (isNewBuffer) ? camera3::dupToAidlIfNotNull(buf) :
+                            aidl::android::hardware::common::NativeHandle();
+            captureRequest->inputBuffer.status = BufferStatus::OK;
+            native_handle_t *acquireFence = nullptr;
+            if (request->input_buffer->acquire_fence != -1) {
+                acquireFence = native_handle_create(1,0);
+                acquireFence->data[0] = request->input_buffer->acquire_fence;
+                handlesCreated->push_back(acquireFence);
+            }
+            // duping here is okay, in aidl ownership is not given to aidl_handle
+            captureRequest->inputBuffer.acquireFence = camera3::dupToAidlIfNotNull(acquireFence);
+            captureRequest->inputBuffer.releaseFence =
+                    aidl::android::hardware::common::NativeHandle();
+
+            mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
+                    request->input_buffer->buffer);
+            inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+        } else {
+            captureRequest->inputBuffer.streamId = -1;
+            captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
+        }
+
+        captureRequest->outputBuffers.resize(request->num_output_buffers);
+        for (size_t i = 0; i < request->num_output_buffers; i++) {
+            const camera_stream_buffer_t *src = request->output_buffers + i;
+            StreamBuffer &dst = captureRequest->outputBuffers[i];
+            int32_t streamId = Camera3Stream::cast(src->stream)->getId();
+            if (src->buffer != nullptr) {
+                buffer_handle_t buf = *(src->buffer);
+                auto pair = getBufferId(buf, streamId);
+                bool isNewBuffer = pair.first;
+                dst.bufferId = pair.second;
+                dst.buffer = isNewBuffer ?
+                        camera3::dupToAidlIfNotNull(buf) :
+                                aidl::android::hardware::common::NativeHandle();
+                native_handle_t *acquireFence = nullptr;
+                if (src->acquire_fence != -1) {
+                    acquireFence = native_handle_create(1,0);
+                    acquireFence->data[0] = src->acquire_fence;
+                    handlesCreated->push_back(acquireFence);
+                }
+                dst.acquireFence = camera3::dupToAidlIfNotNull(acquireFence);
+            } else if (mUseHalBufManager) {
+                // HAL buffer management path
+                dst.bufferId = BUFFER_ID_NO_BUFFER;
+                dst.buffer = aidl::android::hardware::common::NativeHandle();
+                dst.acquireFence = aidl::android::hardware::common::NativeHandle();
+            } else {
+                ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
+                return BAD_VALUE;
+            }
+            dst.streamId = streamId;
+            dst.status = BufferStatus::OK;
+            dst.releaseFence = aidl::android::hardware::common::NativeHandle();
+
+            // Output buffers are empty when using HAL buffer manager
+            if (!mUseHalBufManager) {
+                mBufferRecords.pushInflightBuffer(
+                        captureRequest->frameNumber, streamId, src->buffer);
+                inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+            }
+        }
+    }
+    return OK;
+}
+
+status_t AidlCamera3Device::AidlHalInterface::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/aidl::android::hardware::camera::device::CameraOfflineSessionInfo*
+                offlineSessionInfo,
+        /*out*/std::shared_ptr<aidl::android::hardware::camera::device::ICameraOfflineSession>*
+                offlineSession,
+        /*out*/camera3::BufferRecords* bufferRecords) {
+    ATRACE_NAME("CameraHal::switchToOffline");
+    if (!valid()) {
+        ALOGE("%s called on invalid camera!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
+        ALOGE("%s: output arguments must not be null!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    auto err = mAidlSession->switchToOffline(streamsToKeep, offlineSessionInfo, offlineSession);
+
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
+        return AidlProviderInfo::mapToStatusT(err);
+    }
+
+    return verifyBufferCaches(offlineSessionInfo, bufferRecords);
+}
+
+AidlCamera3Device::AidlRequestThread::AidlRequestThread(wp<Camera3Device> parent,
+                sp<camera3::StatusTracker> statusTracker,
+                sp<HalInterface> interface,
+                const Vector<int32_t>& sessionParamKeys,
+                bool useHalBufManager,
+                bool supportCameraMute) :
+          RequestThread(parent, statusTracker, interface, sessionParamKeys, useHalBufManager,
+                  supportCameraMute) {}
+
+status_t AidlCamera3Device::AidlRequestThread::switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/camera::device::CameraOfflineSessionInfo* offlineSessionInfo,
+        /*out*/std::shared_ptr<camera::device::ICameraOfflineSession>* offlineSession,
+        /*out*/camera3::BufferRecords* bufferRecords) {
+    Mutex::Autolock l(mRequestLock);
+    clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
+
+    // Wait until request thread is fully stopped
+    // TBD: check if request thread is being paused by other APIs (shouldn't be)
+
+    // We could also check for mRepeatingRequests.empty(), but the API interface
+    // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
+    // new requests during the call; hence skip that check.
+    bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+    while (!queueEmpty) {
+        status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
+        if (res == TIMED_OUT) {
+            ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
+            return res;
+        } else if (res != OK) {
+            ALOGE("%s: request thread failed to submit a request: %s (%d)!",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+        queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+    }
+    return (static_cast<AidlHalInterface *>(mInterface.get()))->switchToOffline(
+            streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
+}
+
+status_t AidlCamera3Device::AidlCamera3DeviceInjectionMethods::injectionInitialize(
+        const String8& injectedCamId, sp<CameraProviderManager> manager,
+        const std::shared_ptr<camera::device::ICameraDeviceCallback>&callback) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mInjectionLock);
+
+    if (manager == nullptr) {
+        ALOGE("%s: manager does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (parent->getTransportType() != IPCTransport::AIDL) {
+        ALOGE("%s Parent transport not AIDL for injected camera id %s, aborting", __FUNCTION__,
+                  injectedCamId.c_str());
+        return INVALID_OPERATION;
+    }
+    mInjectedCamId = injectedCamId;
+    std::shared_ptr<camera::device::ICameraInjectionSession> injectionSession;
+    ATRACE_BEGIN("Injection CameraHal::openSession");
+    status_t res = manager->openAidlInjectionSession(injectedCamId.string(), callback,
+                                          /*out*/ &injectionSession);
+    ATRACE_END();
+    if (res != OK) {
+        ALOGE("Injection camera could not open camera session: %s (%d)",
+                strerror(-res), res);
+        return res;
+    }
+    std::shared_ptr<camera::device::ICameraDeviceSession> deviceSession = nullptr;
+    auto ret = injectionSession->getCameraDeviceSession(&deviceSession);
+    if (!ret.isOk() || deviceSession == nullptr) {
+        ALOGE("%s Camera injection session couldn't return ICameraDeviceSession", __FUNCTION__);
+        return AidlProviderInfo::mapToStatusT(ret);
+    }
+
+    std::shared_ptr<AidlRequestMetadataQueue> queue;
+    ::aidl::android::hardware::common::fmq::MQDescriptor<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> desc;
+
+    ::ndk::ScopedAStatus requestQueueRet = deviceSession->getCaptureRequestMetadataQueue(&desc);
+    if (!requestQueueRet.isOk()) {
+        ALOGE("Injection camera transaction error when getting result metadata queue from camera"
+                " session: %s", requestQueueRet.getMessage());
+        return AidlProviderInfo::mapToStatusT(requestQueueRet);
+    }
+    queue = std::make_unique<AidlRequestMetadataQueue>(desc);
+    if (!queue->isValid() || queue->availableToWrite() <= 0) {
+        ALOGE("HAL returns empty result metadata fmq, not use it");
+        queue = nullptr;
+        // Don't use resQueue onwards.
+    }
+
+    std::unique_ptr<AidlResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
+    ::aidl::android::hardware::common::fmq::MQDescriptor<
+        int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> resDesc;
+    ::ndk::ScopedAStatus resultQueueRet = deviceSession->getCaptureResultMetadataQueue(&resDesc);
+    if (!resultQueueRet.isOk()) {
+        ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+                resultQueueRet.getMessage());
+        return AidlProviderInfo::mapToStatusT(resultQueueRet);
+    }
+    resQueue = std::make_unique<AidlResultMetadataQueue>(resDesc);
+    if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+        ALOGE("HAL returns empty result metadata fmq, not use it");
+        resQueue = nullptr;
+        // Don't use resQueue onwards.
+    }
+
+    ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
+
+    mInjectedCamHalInterface =
+            new AidlHalInterface(deviceSession, injectionSession, queue, parent->mUseHalBufManager,
+                       parent->mSupportOfflineProcessing);
+    if (mInjectedCamHalInterface == nullptr) {
+        ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    return OK;
+}
+
+status_t AidlCamera3Device::AidlCamera3DeviceInjectionMethods::replaceHalInterface(
+        sp<HalInterface> newHalInterface, bool keepBackup) {
+    Mutex::Autolock lock(mInjectionLock);
+    if (newHalInterface.get() == nullptr) {
+        ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
+                __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if (parent->getTransportType() != IPCTransport::AIDL ||
+            newHalInterface->getTransportType() != IPCTransport::AIDL) {
+        ALOGE("%s Parent transport not AIDL for replacing hal interface", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    AidlCamera3Device *aidlParent = static_cast<AidlCamera3Device *>(parent.get());
+    if (keepBackup) {
+        if (mBackupHalInterface == nullptr) {
+            mBackupHalInterface = parent->mInterface;
+        }
+        if (mBackupResultMetadataQueue == nullptr) {
+            mBackupResultMetadataQueue = std::move(aidlParent->mResultMetadataQueue);
+            aidlParent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
+        }
+    } else {
+        mBackupHalInterface = nullptr;
+        aidlParent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
+        mBackupResultMetadataQueue = nullptr;
+    }
+    parent->mInterface = newHalInterface;
+    return OK;
+}
+
+status_t AidlCamera3Device::injectionCameraInitialize(const String8 &injectedCamId,
+            sp<CameraProviderManager> manager) {
+        return (static_cast<AidlCamera3DeviceInjectionMethods *>
+                    (mInjectionMethods.get()))->injectionInitialize(injectedCamId, manager,
+                        std::shared_ptr<camera::device::ICameraDeviceCallback>(mCallbacks));
+};
+
+sp<Camera3Device::RequestThread> AidlCamera3Device::createNewRequestThread(
+                wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
+                sp<Camera3Device::HalInterface> interface,
+                const Vector<int32_t>& sessionParamKeys,
+                bool useHalBufManager,
+                bool supportCameraMute) {
+    return new AidlRequestThread(parent, statusTracker, interface, sessionParamKeys,
+            useHalBufManager, supportCameraMute);
+};
+
+sp<Camera3Device::Camera3DeviceInjectionMethods>
+AidlCamera3Device::createCamera3DeviceInjectionMethods(wp<Camera3Device> parent) {
+    return new AidlCamera3DeviceInjectionMethods(parent);
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
new file mode 100644
index 0000000..e7a7eec
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -0,0 +1,273 @@
+/*
+ * 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 ANDROID_SERVERS_AIDLCAMERA3DEVICE_H
+#define ANDROID_SERVERS_AIDLCAMERA3DEVICE_H
+
+#include "../Camera3Device.h"
+#include "AidlCamera3OutputUtils.h"
+#include <fmq/AidlMessageQueue.h>
+
+#include <aidl/android/hardware/camera/device/BnCameraDeviceCallback.h>
+#include <aidl/android/hardware/camera/device/ICameraDevice.h>
+#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
+namespace android {
+
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+/**
+ * CameraDevice for AIDL HAL devices.
+ */
+class AidlCamera3Device :
+            public Camera3Device {
+  public:
+
+    using AidlRequestMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+    class AidlCameraDeviceCallbacks;
+    friend class AidlCameraDeviceCallbacks;
+    explicit AidlCamera3Device(const String8& id, bool overrideForPerfClass,
+            bool legacyClient = false);
+
+    virtual ~AidlCamera3Device() { }
+
+    static aidl::android::hardware::graphics::common::PixelFormat mapToAidlPixelFormat(
+            int frameworkFormat);
+    static aidl::android::hardware::graphics::common::Dataspace mapToAidlDataspace(
+            android_dataspace dataSpace);
+    static aidl::android::hardware::graphics::common::BufferUsage mapToAidlConsumerUsage(
+            uint64_t usage);
+    static aidl::android::hardware::camera::device::StreamRotation
+            mapToAidlStreamRotation(camera_stream_rotation_t rotation);
+
+    static status_t mapToAidlStreamConfigurationMode(
+            camera_stream_configuration_mode_t operationMode,
+            aidl::android::hardware::camera::device::StreamConfigurationMode *mode);
+
+    static int mapToFrameworkFormat(
+        aidl::android::hardware::graphics::common::PixelFormat pixelFormat);
+    static android_dataspace mapToFrameworkDataspace(
+            aidl::android::hardware::graphics::common::Dataspace);
+    static uint64_t mapConsumerToFrameworkUsage(
+            aidl::android::hardware::graphics::common::BufferUsage usage);
+    static uint64_t mapProducerToFrameworkUsage(
+            aidl::android::hardware::graphics::common::BufferUsage usage);
+
+    virtual status_t switchToOffline(const std::vector<int32_t>& /*streamsToKeep*/,
+            /*out*/ sp<CameraOfflineSessionBase>* /*session*/) override;
+
+    status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+    class AidlHalInterface : public Camera3Device::HalInterface {
+     public:
+        AidlHalInterface(std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraDeviceSession> &session,
+                std::shared_ptr<AidlRequestMetadataQueue> queue,
+                bool useHalBufManager, bool supportOfflineProcessing);
+        AidlHalInterface(
+                std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession>
+                    &deviceSession,
+                std::shared_ptr<
+                aidl::android::hardware::camera::device::ICameraInjectionSession> &injectionSession,
+                std::shared_ptr<AidlRequestMetadataQueue> queue,
+                bool useHalBufManager, bool supportOfflineProcessing);
+
+        virtual IPCTransport getTransportType() {return IPCTransport::AIDL; }
+
+
+        // Returns true if constructed with a valid device or session, and not yet cleared
+        virtual bool valid() override;
+
+        // Reset this HalInterface object (does not call close())
+        virtual void clear() override;
+
+        // Caller takes ownership of requestTemplate
+        virtual status_t constructDefaultRequestSettings(camera_request_template templateId,
+                /*out*/ camera_metadata_t **requestTemplate) override;
+
+        virtual status_t configureStreams(const camera_metadata_t *sessionParams,
+                /*inout*/ camera_stream_configuration_t *config,
+                const std::vector<uint32_t>& bufferSizes) override;
+        // The injection camera configures the streams to hal.
+        virtual status_t configureInjectedStreams(
+                const camera_metadata_t* sessionParams,
+                /*inout*/ camera_stream_configuration_t* config,
+                const std::vector<uint32_t>& bufferSizes,
+                const CameraMetadata& cameraCharacteristics) override;
+
+        // When the call succeeds, the ownership of acquire fences in requests is transferred to
+        // HalInterface. More specifically, the current implementation will send the fence to
+        // HAL process and close the FD in cameraserver process. When the call fails, the ownership
+        // of the acquire fence still belongs to the caller.
+        virtual status_t processBatchCaptureRequests(
+                std::vector<camera_capture_request_t*>& requests,
+                /*out*/uint32_t* numRequestProcessed) override;
+
+        // Calls into the HAL interface
+        virtual status_t flush() override;
+        virtual status_t dump(int fd) override;
+        virtual status_t close() override;
+        virtual void signalPipelineDrain(const std::vector<int>& streamIds) override;
+        virtual bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
+                CameraMetadata& newSessionParams) override;
+
+        virtual status_t repeatingRequestEnd(uint32_t ,
+                const std::vector<int32_t> &) override;
+
+        status_t switchToOffline(
+        const std::vector<int32_t>& streamsToKeep,
+        /*out*/aidl::android::hardware::camera::device::CameraOfflineSessionInfo*
+                offlineSessionInfo,
+        /*out*/std::shared_ptr<aidl::android::hardware::camera::device::ICameraOfflineSession>*
+                offlineSession,
+        /*out*/camera3::BufferRecords* bufferRecords);
+
+     private:
+
+        // Always valid
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraDeviceSession>
+                mAidlSession = nullptr;
+        //Valid for injection sessions
+        std::shared_ptr<aidl::android::hardware::camera::device::ICameraInjectionSession>
+                mAidlInjectionSession = nullptr;
+
+        status_t wrapAsAidlRequest(camera_capture_request_t* request,
+                /*out*/aidl::android::hardware::camera::device::CaptureRequest* captureRequest,
+                /*out*/std::vector<native_handle_t*>* handlesCreated,
+                /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
+
+        std::shared_ptr<AidlRequestMetadataQueue> mRequestMetadataQueue;
+    }; // class AidlHalInterface
+
+    /**
+     * Implementation of aidl::android::hardware::camera::device::ICameraDeviceCallback
+     */
+    ::ndk::ScopedAStatus processCaptureResult(
+            const std::vector<aidl::android::hardware::camera::device::CaptureResult>& results);
+    ::ndk::ScopedAStatus notify(
+            const std::vector<aidl::android::hardware::camera::device::NotifyMsg>& msgs);
+
+    ::ndk::ScopedAStatus requestStreamBuffers(
+            const std::vector<aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+            std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+            aidl::android::hardware::camera::device::BufferRequestStatus* status);
+
+    ::ndk::ScopedAStatus returnStreamBuffers(
+            const std::vector<aidl::android::hardware::camera::device::StreamBuffer>& buffers);
+
+    class AidlRequestThread : public Camera3Device::RequestThread {
+      public:
+        AidlRequestThread(wp<Camera3Device> parent,
+                sp<camera3::StatusTracker> statusTracker,
+                sp<HalInterface> interface,
+                const Vector<int32_t>& sessionParamKeys,
+                bool useHalBufManager,
+                bool supportCameraMute);
+
+        status_t switchToOffline(
+                const std::vector<int32_t>& streamsToKeep,
+                /*out*/aidl::android::hardware::camera::device::CameraOfflineSessionInfo*
+                        offlineSessionInfo,
+                /*out*/std::shared_ptr<
+                        aidl::android::hardware::camera::device::ICameraOfflineSession>*
+                                offlineSession,
+                /*out*/camera3::BufferRecords* bufferRecords);
+    }; // class AidlRequestThread
+
+    class AidlCamera3DeviceInjectionMethods : public Camera3DeviceInjectionMethods {
+     public:
+        // Initialize the injection camera and generate an hal interface.
+        status_t injectionInitialize(
+                const String8& injectedCamId, sp<CameraProviderManager> manager,
+                const std::shared_ptr<
+                    aidl::android::hardware::camera::device::ICameraDeviceCallback>&
+                    callback);
+        AidlCamera3DeviceInjectionMethods(wp<Camera3Device> parent) :
+                Camera3DeviceInjectionMethods(parent) { };
+        ~AidlCamera3DeviceInjectionMethods() {}
+     private:
+        // Backup of the original camera hal result FMQ.
+        std::unique_ptr<AidlResultMetadataQueue> mBackupResultMetadataQueue;
+
+        // FMQ writes the result for the injection camera. Must be guarded by
+        // mProcessCaptureResultLock.
+        std::unique_ptr<AidlResultMetadataQueue> mInjectionResultMetadataQueue;
+
+        // Use injection camera hal interface to replace and backup original
+        // camera hal interface.
+        virtual status_t replaceHalInterface(sp<HalInterface> newHalInterface,
+                bool keepBackup) override;
+    };
+
+    // We need a separate class which inherits from AIDL ICameraDeviceCallbacks
+    // since we use the ndk backend for AIDL HAL interfaces. The ndk backend of
+    // ICameraDeviceCallbacks doesn't support sp<> (since it doesn't inherit
+    // from RefBase).
+    // As a result we can't write sp<Camera3Device> = new AidlCamera3Device(...).
+    // It supports std::shared_ptr instead. Other references to
+    // Camera3Device in cameraserver use sp<> widely, so to keep supporting
+    // that, we create a new class which will be managed through std::shared_ptr
+    // internally by AidlCamera3Device.
+    class AidlCameraDeviceCallbacks :
+            public aidl::android::hardware::camera::device::BnCameraDeviceCallback {
+      public:
+
+        AidlCameraDeviceCallbacks(wp<AidlCamera3Device> parent) : mParent(parent)  { }
+        ~AidlCameraDeviceCallbacks() { }
+        ::ndk::ScopedAStatus processCaptureResult(
+                const std::vector<
+                        aidl::android::hardware::camera::device::CaptureResult>& results) override;
+        ::ndk::ScopedAStatus notify(
+                const std::vector<
+                        aidl::android::hardware::camera::device::NotifyMsg>& msgs) override;
+
+        ::ndk::ScopedAStatus requestStreamBuffers(
+                const std::vector<
+                        aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+                std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+                aidl::android::hardware::camera::device::BufferRequestStatus* status) override;
+
+        ::ndk::ScopedAStatus returnStreamBuffers(
+                const std::vector<
+                        aidl::android::hardware::camera::device::StreamBuffer>& buffers) override;
+        private:
+            wp<AidlCamera3Device> mParent = nullptr;
+    };
+
+  private:
+    virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+            sp<CameraProviderManager> manager) override;
+
+    virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> parent,
+                sp<camera3::StatusTracker> statusTracker,
+                sp<HalInterface> interface,
+                const Vector<int32_t>& sessionParamKeys,
+                bool useHalBufManager,
+                bool supportCameraMute) override;
+
+    virtual sp<Camera3DeviceInjectionMethods>
+            createCamera3DeviceInjectionMethods(wp<Camera3Device>) override;
+
+    // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+    std::unique_ptr<AidlResultMetadataQueue> mResultMetadataQueue = nullptr;
+
+    std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks = nullptr;
+
+
+}; // class AidlCamera3Device
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
new file mode 100644
index 0000000..895ce56
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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 "AidlCamera3-OffLnSsn"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+#include <inttypes.h>
+
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include "device3/aidl/AidlCamera3OfflineSession.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/aidl/AidlCamera3OutputUtils.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "utils/CameraTraces.h"
+
+using namespace android::camera3;
+using namespace aidl::android::hardware;
+
+namespace android {
+
+
+AidlCamera3OfflineSession::~AidlCamera3OfflineSession() {
+    ATRACE_CALL();
+    ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.string());
+    AidlCamera3OfflineSession::disconnectSession();
+}
+
+status_t AidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
+    ATRACE_CALL();
+
+    if (mSession == nullptr) {
+        ALOGE("%s: AIDL session is null!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+
+        mListener = listener;
+
+        // setup result FMQ
+        std::unique_ptr<AidlResultMetadataQueue>& resQueue = mResultMetadataQueue;
+        ::aidl::android::hardware::common::fmq::MQDescriptor<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> desc;
+        ::ndk::ScopedAStatus resultQueueRet = mSession->getCaptureResultMetadataQueue(&desc);
+        if (!resultQueueRet.isOk()) {
+            ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+                    resultQueueRet.getMessage());
+            return DEAD_OBJECT;
+        }
+        resQueue = std::make_unique<AidlResultMetadataQueue>(desc);
+        if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+            ALOGE("HAL returns empty result metadata fmq, not use it");
+            resQueue = nullptr;
+            // Don't use resQueue onwards.
+        }
+
+        mStatus = STATUS_ACTIVE;
+    }
+
+    mSession->setCallback(mCallbacks);
+
+    return OK;
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::AidlCameraDeviceCallbacks::processCaptureResult(
+        const std::vector<camera::device::CaptureResult>& results) {
+    sp<AidlCamera3OfflineSession> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->processCaptureResult(results);
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::processCaptureResult(
+        const std::vector<camera::device::CaptureResult>& results) {
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return ::ndk::ScopedAStatus::ok();
+        }
+        listener = mListener.promote();
+    }
+
+    AidlCaptureOutputStates states {
+      {mId,
+        mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
+        *this, mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+    };
+
+    std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+    for (const auto& result : results) {
+        processOneCaptureResultLocked(states, result, result.physicalCameraMetadata);
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::AidlCameraDeviceCallbacks::notify(
+        const std::vector<camera::device::NotifyMsg>& msgs) {
+    sp<AidlCamera3OfflineSession> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->notify(msgs);
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::notify(
+        const std::vector<camera::device::NotifyMsg>& msgs) {
+    sp<NotificationListener> listener;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return ::ndk::ScopedAStatus::ok();
+        }
+        listener = mListener.promote();
+    }
+
+    AidlCaptureOutputStates states {
+      {mId,
+        mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+        mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+        mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+        mNextShutterFrameNumber,
+        mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+        mNextResultFrameNumber,
+        mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+        mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+        mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+        mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+        mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
+        *this, mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+    };
+    for (const auto& msg : msgs) {
+        camera3::notify(states, msg);
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::AidlCameraDeviceCallbacks::requestStreamBuffers(
+        const std::vector<::aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+        std::vector<::aidl::android::hardware::camera::device::StreamBufferRet>* buffers,
+        ::aidl::android::hardware::camera::device::BufferRequestStatus* status) {
+    sp<AidlCamera3OfflineSession> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->requestStreamBuffers(bufReqs, buffers, status);
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::requestStreamBuffers(
+        const std::vector<::aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+        std::vector<::aidl::android::hardware::camera::device::StreamBufferRet>* buffers,
+        ::aidl::android::hardware::camera::device::BufferRequestStatus* status) {
+
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return ::ndk::ScopedAStatus::ok();
+        }
+    }
+
+    RequestBufferStates states {
+        mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+        *this, mBufferRecords, *this};
+    camera3::requestStreamBuffers(states, bufReqs, buffers, status);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::AidlCameraDeviceCallbacks::returnStreamBuffers(
+        const std::vector<camera::device::StreamBuffer>& buffers) {
+    sp<AidlCamera3OfflineSession> p = mParent.promote();
+    if (p == nullptr) {
+        ALOGE("%s Parent AidlCameraDevice not alive, can't process callbacks", __FUNCTION__);
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return p->returnStreamBuffers(buffers);
+}
+
+::ndk::ScopedAStatus AidlCamera3OfflineSession::returnStreamBuffers(
+        const std::vector<camera::device::StreamBuffer>& buffers) {
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mStatus != STATUS_ACTIVE) {
+            ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+            return ::ndk::ScopedAStatus::ok();
+        }
+    }
+
+    ReturnBufferStates states {
+        mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+        mBufferRecords};
+
+    camera3::returnStreamBuffers(states, buffers);
+    return ::ndk::ScopedAStatus::ok();
+}
+
+void AidlCamera3OfflineSession::disconnectSession() {
+  std::lock_guard<std::mutex> lock(mLock);
+  if (mSession != nullptr) {
+      mSession->close();
+  }
+  mSession.reset();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
new file mode 100644
index 0000000..ad4a480
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.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 ANDROID_SERVERS_AIDL_CAMERA3OFFLINESESSION_H
+#define ANDROID_SERVERS_AIDL_CAMERA3OFFLINESESSION_H
+
+#include <memory>
+#include <mutex>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include "AidlCamera3OutputUtils.h"
+#include <aidl/android/hardware/camera/device/BnCameraDeviceCallback.h>
+#include <aidl/android/hardware/camera/device/ICameraOfflineSession.h>
+
+#include <fmq/AidlMessageQueue.h>
+
+#include "common/CameraOfflineSessionBase.h"
+
+#include "device3/Camera3BufferManager.h"
+#include "device3/Camera3OfflineSession.h"
+#include "utils/TagMonitor.h"
+#include <camera_metadata_hidden.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3Stream;
+class Camera3OutputStreamInterface;
+class Camera3StreamInterface;
+
+} // namespace camera3
+
+/**
+ * AidlCamera3OfflineSession for offline session defined in AIDL ICameraOfflineSession
+ */
+class AidlCamera3OfflineSession :
+            public Camera3OfflineSession {
+  public:
+
+    virtual ~AidlCamera3OfflineSession();
+
+    virtual status_t initialize(wp<NotificationListener> listener) override;
+
+    /**
+     * Implementation of aidl::android::hardware::camera::device::ICameraDeviceCallback
+     */
+    ::ndk::ScopedAStatus processCaptureResult(
+            const std::vector<aidl::android::hardware::camera::device::CaptureResult>& results);
+    ::ndk::ScopedAStatus notify(
+            const std::vector<aidl::android::hardware::camera::device::NotifyMsg>& msgs);
+    ::ndk::ScopedAStatus requestStreamBuffers(
+            const std::vector<aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+            std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+            aidl::android::hardware::camera::device::BufferRequestStatus* status);
+
+    ::ndk::ScopedAStatus returnStreamBuffers(
+            const std::vector<aidl::android::hardware::camera::device::StreamBuffer>& buffers);
+
+    // See explanation for why we need a separate class for this in
+    // AidlCamera3Device::AidlCameraDeviceCallbacks in AidlCamera3Device.h
+    class AidlCameraDeviceCallbacks :
+            virtual public aidl::android::hardware::camera::device::BnCameraDeviceCallback {
+      public:
+
+        AidlCameraDeviceCallbacks(wp<AidlCamera3OfflineSession> parent) : mParent(parent)  { }
+        ~AidlCameraDeviceCallbacks() {}
+        ::ndk::ScopedAStatus processCaptureResult(
+                const std::vector<
+                        aidl::android::hardware::camera::device::CaptureResult>& results) override;
+        ::ndk::ScopedAStatus notify(
+                const std::vector<
+                        aidl::android::hardware::camera::device::NotifyMsg>& msgs) override;
+
+        ::ndk::ScopedAStatus requestStreamBuffers(
+                const std::vector<
+                        aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+                std::vector<aidl::android::hardware::camera::device::StreamBufferRet>* out_buffers,
+                aidl::android::hardware::camera::device::BufferRequestStatus* _aidl_return
+                ) override;
+
+        ::ndk::ScopedAStatus returnStreamBuffers(
+                const std::vector<
+                        aidl::android::hardware::camera::device::StreamBuffer>& buffers) override;
+        private:
+            wp<AidlCamera3OfflineSession> mParent = nullptr;
+    };
+
+    // initialize by Camera3Device.
+    explicit AidlCamera3OfflineSession(const String8& id,
+            const sp<camera3::Camera3Stream>& inputStream,
+            const camera3::StreamSet& offlineStreamSet,
+            camera3::BufferRecords&& bufferRecords,
+            const camera3::InFlightRequestMap& offlineReqs,
+            const Camera3OfflineStates& offlineStates,
+            std::shared_ptr<aidl::android::hardware::camera::device::ICameraOfflineSession>
+                    offlineSession) :
+      Camera3OfflineSession(id, inputStream, offlineStreamSet, std::move(bufferRecords),
+              offlineReqs, offlineStates),
+      mSession(offlineSession) { mCallbacks = std::make_shared<AidlCameraDeviceCallbacks>(this);};
+
+    /**
+     * End of CameraOfflineSessionBase interface
+     */
+
+  private:
+    std::shared_ptr<aidl::android::hardware::camera::device::ICameraOfflineSession> mSession;
+    // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+    std::unique_ptr<AidlResultMetadataQueue> mResultMetadataQueue;
+
+    std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks;
+
+    virtual void disconnectSession() override;
+
+}; // class AidlCamera3OfflineSession
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
new file mode 100644
index 0000000..3809f37
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
@@ -0,0 +1,341 @@
+/*
+ * 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 "AidlCamera3-OutputUtils"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) states.setErrIntf.setErrorState(   \
+    "%s: " fmt, __FUNCTION__,                         \
+    ##__VA_ARGS__)
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <aidlcommonsupport/NativeHandle.h>
+
+#include <camera/CameraUtils.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/aidl/AidlCamera3OutputUtils.h"
+#include "device3/Camera3OutputUtilsTemplated.h"
+
+#include "system/camera_metadata.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+void processOneCaptureResultLocked(
+        AidlCaptureOutputStates& states,
+        const aidl::android::hardware::camera::device::CaptureResult& result,
+        const std::vector<aidl::android::hardware::camera::device::PhysicalCameraMetadata>
+                &physicalCameraMetadata) {
+    processOneCaptureResultLockedT<AidlCaptureOutputStates,
+        aidl::android::hardware::camera::device::CaptureResult,
+        std::vector<aidl::android::hardware::camera::device::PhysicalCameraMetadata>,
+        std::vector<uint8_t>, AidlResultMetadataQueue,
+        aidl::android::hardware::camera::device::BufferStatus, int8_t>(states, result,
+                physicalCameraMetadata);
+}
+
+void notify(CaptureOutputStates& states,
+        const aidl::android::hardware::camera::device::NotifyMsg& msg) {
+
+    using ErrorCode = aidl::android::hardware::camera::device::ErrorCode;
+    using Tag = aidl::android::hardware::camera::device::NotifyMsg::Tag;
+
+    ATRACE_CALL();
+    camera_notify_msg m;
+
+    switch (msg.getTag()) {
+        case Tag::error:
+            m.type = CAMERA_MSG_ERROR;
+            m.message.error.frame_number = msg.get<Tag::error>().frameNumber;
+            if (msg.get<Tag::error>().errorStreamId >= 0) {
+                sp<Camera3StreamInterface> stream =
+                        states.outputStreams.get(msg.get<Tag::error>().errorStreamId);
+                if (stream == nullptr) {
+                    ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
+                            m.message.error.frame_number, msg.get<Tag::error>().errorStreamId);
+                    return;
+                }
+                m.message.error.error_stream = stream->asHalStream();
+            } else {
+                m.message.error.error_stream = nullptr;
+            }
+            switch (msg.get<Tag::error>().errorCode) {
+                case ErrorCode::ERROR_DEVICE:
+                    m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
+                    break;
+                case ErrorCode::ERROR_REQUEST:
+                    m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
+                    break;
+                case ErrorCode::ERROR_RESULT:
+                    m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
+                    break;
+                case ErrorCode::ERROR_BUFFER:
+                    m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
+                    break;
+            }
+            break;
+        case Tag::shutter:
+            m.type = CAMERA_MSG_SHUTTER;
+            m.message.shutter.frame_number = msg.get<Tag::shutter>().frameNumber;
+            m.message.shutter.timestamp = msg.get<Tag::shutter>().timestamp;
+            m.message.shutter.readout_timestamp = msg.get<Tag::shutter>().readoutTimestamp;
+            break;
+    }
+    notify(states, &m);
+}
+
+
+// The buffers requested through this call are not tied to any CaptureRequest in
+// particular. They may used by the hal for a particular frame's output buffer
+// or for its internal use as well. In the case that the hal does use any buffer
+// from the requested list here, for a particular frame's output buffer, the
+// buffer will be returned with the processCaptureResult call corresponding to
+// the frame. The other buffers will be returned through returnStreamBuffers.
+// The buffers returned via returnStreamBuffers will not have a valid
+// timestamp(0) and will be dropped by the bufferqueue.
+void requestStreamBuffers(RequestBufferStates& states,
+        const std::vector<aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+        std::vector<::aidl::android::hardware::camera::device::StreamBufferRet>* outBuffers,
+        ::aidl::android::hardware::camera::device::BufferRequestStatus* status) {
+    using aidl::android::hardware::camera::device::BufferStatus;
+    using aidl::android::hardware::camera::device::StreamBuffer;
+    using aidl::android::hardware::camera::device::BufferRequestStatus;
+    using aidl::android::hardware::camera::device::StreamBufferRet;
+    using aidl::android::hardware::camera::device::StreamBufferRequestError;
+    using Tag = aidl::android::hardware::camera::device::StreamBuffersVal::Tag;
+    if (outBuffers == nullptr || status == nullptr) {
+        ALOGE("%s outBuffers / buffer status nullptr", __FUNCTION__);
+        return;
+    }
+    std::lock_guard<std::mutex> lock(states.reqBufferLock);
+    std::vector<StreamBufferRet> bufRets;
+    outBuffers->clear();
+    if (!states.useHalBufManager) {
+        ALOGE("%s: Camera %s does not support HAL buffer management",
+                __FUNCTION__, states.cameraId.string());
+        *status = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
+        return;
+    }
+
+    SortedVector<int32_t> streamIds;
+    ssize_t sz = streamIds.setCapacity(bufReqs.size());
+    if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
+        ALOGE("%s: failed to allocate memory for %zu buffer requests",
+                __FUNCTION__, bufReqs.size());
+        *status = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
+        return;
+    }
+
+    if (bufReqs.size() > states.outputStreams.size()) {
+        ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
+                __FUNCTION__, bufReqs.size(), states.outputStreams.size());
+        *status = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
+        return;
+    }
+
+    // Check for repeated streamId
+    for (const auto& bufReq : bufReqs) {
+        if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
+            ALOGE("%s: Stream %d appear multiple times in buffer requests",
+                    __FUNCTION__, bufReq.streamId);
+            *status = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
+            return;
+        }
+        streamIds.add(bufReq.streamId);
+    }
+
+    if (!states.reqBufferIntf.startRequestBuffer()) {
+        ALOGE("%s: request buffer disallowed while camera service is configuring",
+                __FUNCTION__);
+        *status = BufferRequestStatus::FAILED_CONFIGURING;
+        return;
+    }
+
+    bufRets.resize(bufReqs.size());
+
+    bool allReqsSucceeds = true;
+    bool oneReqSucceeds = false;
+    for (size_t i = 0; i < bufReqs.size(); i++) {
+        const auto& bufReq = bufReqs[i];
+        auto& bufRet = bufRets[i];
+        int32_t streamId = bufReq.streamId;
+        sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
+        if (outputStream == nullptr) {
+            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
+            std::vector<StreamBufferRet> emptyBufRets;
+            *status = BufferRequestStatus::FAILED_CONFIGURING;
+            states.reqBufferIntf.endRequestBuffer();
+            return;
+        }
+
+        bufRet.streamId = streamId;
+        if (outputStream->isAbandoned()) {
+            bufRet.val.set<Tag::error>(StreamBufferRequestError::STREAM_DISCONNECTED);
+            allReqsSucceeds = false;
+            continue;
+        }
+
+        size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
+        uint32_t numBuffersRequested = bufReq.numBuffersRequested;
+        size_t totalHandout = handOutBufferCount + numBuffersRequested;
+        uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
+        if (totalHandout > maxBuffers) {
+            // Not able to allocate enough buffer. Exit early for this stream
+            ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
+                    " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
+                    numBuffersRequested, maxBuffers);
+            bufRet.val.set<Tag::error>(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
+            allReqsSucceeds = false;
+            continue;
+        }
+
+        std::vector<StreamBuffer> tmpRetBuffers(numBuffersRequested);
+        bool currentReqSucceeds = true;
+        std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
+        std::vector<buffer_handle_t> newBuffers;
+        size_t numAllocatedBuffers = 0;
+        size_t numPushedInflightBuffers = 0;
+        for (size_t b = 0; b < numBuffersRequested; b++) {
+            camera_stream_buffer_t& sb = streamBuffers[b];
+            // Since this method can run concurrently with request thread
+            // We need to update the wait duration everytime we call getbuffer
+            nsecs_t waitDuration =  states.reqBufferIntf.getWaitDuration();
+            status_t res = outputStream->getBuffer(&sb, waitDuration);
+            if (res != OK) {
+                if (res == NO_INIT || res == DEAD_OBJECT) {
+                    ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                    bufRet.val.set<Tag::error>(StreamBufferRequestError::STREAM_DISCONNECTED);
+                    states.sessionStatsBuilder.stopCounter(streamId);
+                } else {
+                    ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                    if (res == TIMED_OUT || res == NO_MEMORY) {
+                        bufRet.val.set<Tag::error>(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+                    } else {
+                        bufRet.val.set<Tag::error>(StreamBufferRequestError::UNKNOWN_ERROR);
+                    }
+                }
+                currentReqSucceeds = false;
+                break;
+            }
+            numAllocatedBuffers++;
+
+            buffer_handle_t *buffer = sb.buffer;
+            auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
+            bool isNewBuffer = pair.first;
+            uint64_t bufferId = pair.second;
+            StreamBuffer& hBuf = tmpRetBuffers[b];
+
+            hBuf.streamId = streamId;
+            hBuf.bufferId = bufferId;
+
+            hBuf.buffer = (isNewBuffer) ? camera3::dupToAidlIfNotNull(*buffer) :
+                    aidl::android::hardware::common::NativeHandle();
+            hBuf.status = BufferStatus::OK;
+            hBuf.releaseFence =  aidl::android::hardware::common::NativeHandle();
+            if (isNewBuffer) {
+                newBuffers.push_back(*buffer);
+            }
+
+            native_handle_t *acquireFence = nullptr;
+            if (sb.acquire_fence != -1) {
+                acquireFence = native_handle_create(1,0);
+                acquireFence->data[0] = sb.acquire_fence;
+            }
+            //makeToAidl passes ownership to aidl NativeHandle made. Ownership
+            //is passed : see system/window.h : dequeueBuffer
+            hBuf.acquireFence = makeToAidlIfNotNull(acquireFence);
+            if (acquireFence != nullptr) {
+                native_handle_delete(acquireFence);
+            }
+            hBuf.releaseFence =  aidl::android::hardware::common::NativeHandle();
+
+            res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
+            if (res != OK) {
+                ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
+                        __FUNCTION__, streamId, strerror(-res), res);
+                bufRet.val.set<Tag::error>(StreamBufferRequestError::UNKNOWN_ERROR);
+                currentReqSucceeds = false;
+                break;
+            }
+            numPushedInflightBuffers++;
+        }
+        if (currentReqSucceeds) {
+            bufRet.val.set<Tag::buffers>(std::move(tmpRetBuffers));
+            oneReqSucceeds = true;
+        } else {
+            allReqsSucceeds = false;
+            for (size_t b = 0; b < numPushedInflightBuffers; b++) {
+                StreamBuffer& hBuf = tmpRetBuffers[b];
+                buffer_handle_t* buffer;
+                status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
+                        hBuf.bufferId, &buffer);
+                if (res != OK) {
+                    SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
+                            __FUNCTION__, streamId, strerror(-res), res);
+                }
+            }
+            for (size_t b = 0; b < numAllocatedBuffers; b++) {
+                camera_stream_buffer_t& sb = streamBuffers[b];
+                sb.acquire_fence = -1;
+                sb.status = CAMERA_BUFFER_STATUS_ERROR;
+            }
+            returnOutputBuffers(states.useHalBufManager, nullptr,
+                    streamBuffers.data(), numAllocatedBuffers, 0,
+                    0, false,
+                    0, states.sessionStatsBuilder);
+            for (auto buf : newBuffers) {
+                states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
+            }
+        }
+    }
+
+    *status = allReqsSucceeds ? BufferRequestStatus::OK :
+            oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
+                             BufferRequestStatus::FAILED_UNKNOWN,
+    // Transfer ownership of buffer fds to outBuffers
+    *outBuffers = std::move(bufRets);
+
+    states.reqBufferIntf.endRequestBuffer();
+}
+
+void returnStreamBuffers(ReturnBufferStates& states,
+        const std::vector<aidl::android::hardware::camera::device::StreamBuffer>& buffers) {
+    returnStreamBuffersT(states, buffers);
+}
+
+} // camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.h
new file mode 100644
index 0000000..e795624
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.h
@@ -0,0 +1,100 @@
+/*
+ * 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 ANDROID_SERVERS_AIDL_CAMERA3_OUTPUT_UTILS_H
+#define ANDROID_SERVERS_AIDL_CAMERA3_OUTPUT_UTILS_H
+
+#include <memory>
+#include <mutex>
+
+#include <cutils/native_handle.h>
+
+#include <aidlcommonsupport/NativeHandle.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include <common/CameraDeviceBase.h>
+
+#include <aidl/android/hardware/camera/device/ICameraDevice.h>
+#include <aidl/android/hardware/camera/device/ICameraDeviceCallback.h>
+#include "device3/BufferUtils.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3Stream.h"
+#include "device3/Camera3OutputStreamInterface.h"
+#include "device3/Camera3OutputUtils.h"
+#include "utils/SessionStatsBuilder.h"
+#include "utils/TagMonitor.h"
+
+namespace android {
+
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using AidlResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+namespace camera3 {
+    inline aidl::android::hardware::common::NativeHandle dupToAidlIfNotNull(
+            const native_handle_t *nh) {
+        if (nh == nullptr) {
+            return aidl::android::hardware::common::NativeHandle();
+        }
+        return dupToAidl(nh);
+    }
+
+    inline aidl::android::hardware::common::NativeHandle makeToAidlIfNotNull(
+            const native_handle_t *nh) {
+        if (nh == nullptr) {
+            return aidl::android::hardware::common::NativeHandle();
+        }
+        return makeToAidl(nh);
+    }
+
+    /**
+     * Helper methods shared between AidlCamera3Device/AidlCamera3OfflineSession for HAL callbacks
+     */
+
+    // Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
+    // callbacks
+    struct AidlCaptureOutputStates : public CaptureOutputStates {
+        std::unique_ptr<AidlResultMetadataQueue>& fmq;
+    };
+
+    // Handle one capture result. Assume callers hold the lock to serialize all
+    // processCaptureResult calls
+    void processOneCaptureResultLocked(
+            AidlCaptureOutputStates& states,
+            const aidl::android::hardware::camera::device::CaptureResult& result,
+            const std::vector<aidl::android::hardware::camera::device::PhysicalCameraMetadata>
+                    &physicalCameraMetadata);
+
+    void notify(CaptureOutputStates& states,
+        const aidl::android::hardware::camera::device::NotifyMsg& msg,
+        bool hasReadoutTime, uint64_t readoutTime);
+
+    void notify(CaptureOutputStates& states,
+        const aidl::android::hardware::camera::device::NotifyMsg& msg);
+
+    void requestStreamBuffers(RequestBufferStates& states,
+        const std::vector<aidl::android::hardware::camera::device::BufferRequest>& bufReqs,
+        std::vector<::aidl::android::hardware::camera::device::StreamBufferRet>* out_buffers,
+        ::aidl::android::hardware::camera::device::BufferRequestStatus* _aidl_return);
+
+    void returnStreamBuffers(ReturnBufferStates& states,
+        const std::vector<aidl::android::hardware::camera::device::StreamBuffer>& buffers);
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
index afe9d56..1563dcf 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
@@ -38,6 +38,8 @@
 #include <camera_metadata_hidden.h>
 
 #include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/aidl/AidlCamera3OutputUtils.h"
+#include "device3/Camera3Device.h"
 #include "device3/Camera3OutputUtilsTemplated.h"
 
 #include "system/camera_metadata.h"
@@ -132,7 +134,116 @@
     notify(states, &m);
 }
 
+static void convertToAidl(
+        const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& hidlBufReqs,
+        std::vector<aidl::android::hardware::camera::device::BufferRequest> &aidlBufReqs) {
+    size_t i = 0;
+    aidlBufReqs.resize(hidlBufReqs.size());
+    for (const auto &hidlBufReq : hidlBufReqs) {
+        aidlBufReqs[i].streamId = hidlBufReq.streamId;
+        aidlBufReqs[i].numBuffersRequested = hidlBufReq.numBuffersRequested;
+        i++;
+    }
+}
 
+static hardware::camera::device::V3_5::StreamBufferRequestError
+convertToHidl(aidl::android::hardware::camera::device::StreamBufferRequestError aError) {
+    using AError = aidl::android::hardware::camera::device::StreamBufferRequestError;
+    using HError = hardware::camera::device::V3_5::StreamBufferRequestError;
+
+    switch(aError) {
+        case AError::NO_BUFFER_AVAILABLE:
+            return HError::NO_BUFFER_AVAILABLE;
+        case AError::MAX_BUFFER_EXCEEDED:
+            return HError::MAX_BUFFER_EXCEEDED;
+        case AError::STREAM_DISCONNECTED:
+            return HError::STREAM_DISCONNECTED;
+        default:
+            return HError::UNKNOWN_ERROR;
+    }
+}
+
+static hardware::camera::device::V3_5::BufferRequestStatus
+convertToHidl(const aidl::android::hardware::camera::device::BufferRequestStatus &aBufStatus) {
+    using AStatus = aidl::android::hardware::camera::device::BufferRequestStatus;
+    using HStatus = hardware::camera::device::V3_5::BufferRequestStatus;
+    switch (aBufStatus) {
+        case AStatus::OK:
+            return HStatus::OK;
+        case AStatus::FAILED_PARTIAL:
+            return HStatus::FAILED_PARTIAL;
+        case AStatus::FAILED_CONFIGURING:
+            return HStatus::FAILED_CONFIGURING;
+        case AStatus::FAILED_ILLEGAL_ARGUMENTS:
+            return HStatus::FAILED_ILLEGAL_ARGUMENTS;
+        case AStatus::FAILED_UNKNOWN:
+            return HStatus::FAILED_UNKNOWN;
+    }
+    return HStatus::FAILED_UNKNOWN;
+}
+
+static hardware::camera::device::V3_2::BufferStatus
+convertToHidl(const aidl::android::hardware::camera::device::BufferStatus &aBufStatus) {
+    using AStatus = aidl::android::hardware::camera::device::BufferStatus;
+    using HStatus = hardware::camera::device::V3_2::BufferStatus;
+    switch (aBufStatus) {
+        case AStatus::OK:
+            return HStatus::OK;
+        case AStatus::ERROR:
+            return HStatus::ERROR;
+    }
+    return HStatus::ERROR;
+}
+
+static native_handle_t *convertToHidl(const aidl::android::hardware::common::NativeHandle &ah,
+        std::vector<native_handle_t *> &handlesCreated) {
+    if (isHandleNull(ah)) {
+        return nullptr;
+    }
+    native_handle_t *nh = makeFromAidl(ah);
+    handlesCreated.emplace_back(nh);
+    return nh;
+}
+
+static void convertToHidl(
+        const std::vector<aidl::android::hardware::camera::device::StreamBuffer> &aBuffers,
+        hardware::camera::device::V3_5::StreamBuffersVal &hBuffersVal,
+        std::vector<native_handle_t *> &handlesCreated) {
+    using HStreamBuffer = hardware::camera::device::V3_2::StreamBuffer;
+    hardware::hidl_vec<HStreamBuffer> tmpBuffers(aBuffers.size());
+    size_t i = 0;
+    for (const auto &aBuf : aBuffers) {
+        tmpBuffers[i].status = convertToHidl(aBuf.status);
+        tmpBuffers[i].streamId = aBuf.streamId;
+        tmpBuffers[i].bufferId = aBuf.bufferId;
+        tmpBuffers[i].buffer = convertToHidl(aBuf.buffer, handlesCreated);
+        tmpBuffers[i].acquireFence = convertToHidl(aBuf.acquireFence, handlesCreated);
+        tmpBuffers[i].releaseFence = convertToHidl(aBuf.releaseFence, handlesCreated);
+    }
+    hBuffersVal.buffers(std::move(tmpBuffers));
+}
+
+static void convertToHidl(
+        const std::vector<aidl::android::hardware::camera::device::StreamBufferRet> &aidlBufRets,
+        hardware::hidl_vec<hardware::camera::device::V3_5::StreamBufferRet> &hidlBufRets,
+        std::vector<native_handle_t *> &handlesCreated) {
+    size_t i = 0;
+    using Tag = aidl::android::hardware::camera::device::StreamBuffersVal::Tag;
+    hidlBufRets.resize(aidlBufRets.size());
+    for (const auto &aidlBufRet : aidlBufRets) {
+        auto &hidlBufRet = hidlBufRets[i];
+        hidlBufRet.streamId = aidlBufRet.streamId;
+        switch(aidlBufRet.val.getTag()) {
+          case Tag::error:
+              hidlBufRet.val.error(convertToHidl(aidlBufRet.val.get<Tag::error>()));
+              break;
+          case Tag::buffers:
+              convertToHidl(aidlBufRet.val.get<Tag::buffers>(), hidlBufRet.val, handlesCreated);
+              break;
+        }
+        i++;
+    }
+}
 
 // The buffers requested through this call are not tied to any CaptureRequest in
 // particular. They may used by the hal for a particular frame's output buffer
@@ -145,194 +256,22 @@
 void requestStreamBuffers(RequestBufferStates& states,
         const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
         hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
-    using android::hardware::camera::device::V3_2::BufferStatus;
+   using android::hardware::camera::device::V3_2::BufferStatus;
     using android::hardware::camera::device::V3_2::StreamBuffer;
     using android::hardware::camera::device::V3_5::BufferRequestStatus;
     using android::hardware::camera::device::V3_5::StreamBufferRet;
     using android::hardware::camera::device::V3_5::StreamBufferRequestError;
+    std::vector<aidl::android::hardware::camera::device::BufferRequest> aidlBufReqs;
+    hardware::hidl_vec<hardware::camera::device::V3_5::StreamBufferRet> hidlBufRets;
+    convertToAidl(bufReqs, aidlBufReqs);
+    std::vector<::aidl::android::hardware::camera::device::StreamBufferRet> aidlBufRets;
+    ::aidl::android::hardware::camera::device::BufferRequestStatus aidlBufRetStatus;
 
-    std::lock_guard<std::mutex> lock(states.reqBufferLock);
-
-    hardware::hidl_vec<StreamBufferRet> bufRets;
-    if (!states.useHalBufManager) {
-        ALOGE("%s: Camera %s does not support HAL buffer management",
-                __FUNCTION__, states.cameraId.string());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return;
-    }
-
-    SortedVector<int32_t> streamIds;
-    ssize_t sz = streamIds.setCapacity(bufReqs.size());
-    if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
-        ALOGE("%s: failed to allocate memory for %zu buffer requests",
-                __FUNCTION__, bufReqs.size());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return;
-    }
-
-    if (bufReqs.size() > states.outputStreams.size()) {
-        ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
-                __FUNCTION__, bufReqs.size(), states.outputStreams.size());
-        _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-        return;
-    }
-
-    // Check for repeated streamId
-    for (const auto& bufReq : bufReqs) {
-        if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
-            ALOGE("%s: Stream %d appear multiple times in buffer requests",
-                    __FUNCTION__, bufReq.streamId);
-            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
-            return;
-        }
-        streamIds.add(bufReq.streamId);
-    }
-
-    if (!states.reqBufferIntf.startRequestBuffer()) {
-        ALOGE("%s: request buffer disallowed while camera service is configuring",
-                __FUNCTION__);
-        _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
-        return;
-    }
-
-    bufRets.resize(bufReqs.size());
-
-    bool allReqsSucceeds = true;
-    bool oneReqSucceeds = false;
-    for (size_t i = 0; i < bufReqs.size(); i++) {
-        const auto& bufReq = bufReqs[i];
-        auto& bufRet = bufRets[i];
-        int32_t streamId = bufReq.streamId;
-        sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
-        if (outputStream == nullptr) {
-            ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
-            hardware::hidl_vec<StreamBufferRet> emptyBufRets;
-            _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
-            states.reqBufferIntf.endRequestBuffer();
-            return;
-        }
-
-        bufRet.streamId = streamId;
-        if (outputStream->isAbandoned()) {
-            bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
-            allReqsSucceeds = false;
-            continue;
-        }
-
-        size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
-        uint32_t numBuffersRequested = bufReq.numBuffersRequested;
-        size_t totalHandout = handOutBufferCount + numBuffersRequested;
-        uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
-        if (totalHandout > maxBuffers) {
-            // Not able to allocate enough buffer. Exit early for this stream
-            ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
-                    " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
-                    numBuffersRequested, maxBuffers);
-            bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
-            allReqsSucceeds = false;
-            continue;
-        }
-
-        hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
-        bool currentReqSucceeds = true;
-        std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
-        std::vector<buffer_handle_t> newBuffers;
-        size_t numAllocatedBuffers = 0;
-        size_t numPushedInflightBuffers = 0;
-        for (size_t b = 0; b < numBuffersRequested; b++) {
-            camera_stream_buffer_t& sb = streamBuffers[b];
-            // Since this method can run concurrently with request thread
-            // We need to update the wait duration everytime we call getbuffer
-            nsecs_t waitDuration =  states.reqBufferIntf.getWaitDuration();
-            status_t res = outputStream->getBuffer(&sb, waitDuration);
-            if (res != OK) {
-                if (res == NO_INIT || res == DEAD_OBJECT) {
-                    ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                    bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
-                    states.sessionStatsBuilder.stopCounter(streamId);
-                } else {
-                    ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                    if (res == TIMED_OUT || res == NO_MEMORY) {
-                        bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
-                    } else {
-                        bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
-                    }
-                }
-                currentReqSucceeds = false;
-                break;
-            }
-            numAllocatedBuffers++;
-
-            buffer_handle_t *buffer = sb.buffer;
-            auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
-            bool isNewBuffer = pair.first;
-            uint64_t bufferId = pair.second;
-            StreamBuffer& hBuf = tmpRetBuffers[b];
-
-            hBuf.streamId = streamId;
-            hBuf.bufferId = bufferId;
-            hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
-            hBuf.status = BufferStatus::OK;
-            hBuf.releaseFence = nullptr;
-            if (isNewBuffer) {
-                newBuffers.push_back(*buffer);
-            }
-
-            native_handle_t *acquireFence = nullptr;
-            if (sb.acquire_fence != -1) {
-                acquireFence = native_handle_create(1,0);
-                acquireFence->data[0] = sb.acquire_fence;
-            }
-            hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
-            hBuf.releaseFence = nullptr;
-
-            res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
-            if (res != OK) {
-                ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
-                        __FUNCTION__, streamId, strerror(-res), res);
-                bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
-                currentReqSucceeds = false;
-                break;
-            }
-            numPushedInflightBuffers++;
-        }
-        if (currentReqSucceeds) {
-            bufRet.val.buffers(std::move(tmpRetBuffers));
-            oneReqSucceeds = true;
-        } else {
-            allReqsSucceeds = false;
-            for (size_t b = 0; b < numPushedInflightBuffers; b++) {
-                StreamBuffer& hBuf = tmpRetBuffers[b];
-                buffer_handle_t* buffer;
-                status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
-                        hBuf.bufferId, &buffer);
-                if (res != OK) {
-                    SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
-                            __FUNCTION__, streamId, strerror(-res), res);
-                }
-            }
-            for (size_t b = 0; b < numAllocatedBuffers; b++) {
-                camera_stream_buffer_t& sb = streamBuffers[b];
-                sb.acquire_fence = -1;
-                sb.status = CAMERA_BUFFER_STATUS_ERROR;
-            }
-            returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
-                    streamBuffers.data(), numAllocatedBuffers, /*timestamp*/0,
-                    /*readoutTimestamp*/0, /*requested*/false,
-                    /*requestTimeNs*/0, states.sessionStatsBuilder);
-            for (auto buf : newBuffers) {
-                states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
-            }
-        }
-    }
-
-    _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
-            oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
-                             BufferRequestStatus::FAILED_UNKNOWN,
-            bufRets);
-    states.reqBufferIntf.endRequestBuffer();
+    requestStreamBuffers(states, aidlBufReqs, &aidlBufRets, &aidlBufRetStatus);
+    std::vector<native_handle_t *> handlesCreated;
+    convertToHidl(aidlBufRets, hidlBufRets, handlesCreated);
+    _hidl_cb(convertToHidl(aidlBufRetStatus), hidlBufRets);
+    Camera3Device::cleanupNativeHandles(&handlesCreated);
 }
 
 void returnStreamBuffers(ReturnBufferStates& states,
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index ca73e4c..3c98a5e 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -52,6 +52,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V1-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index c3f0620..4928faf 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -44,6 +44,7 @@
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V1-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.4",
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 751f24f..ddcbdee 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -21,7 +21,9 @@
 #include "../api2/HeicCompositeStream.h"
 #include "android/hardware/camera/metadata/3.8/types.h"
 #include "common/CameraDeviceBase.h"
+#include "common/HalConversionsTemplated.h"
 #include "../CameraService.h"
+#include "device3/aidl/AidlCamera3Device.h"
 #include "device3/hidl/HidlCamera3Device.h"
 #include "device3/Camera3OutputStream.h"
 #include "system/graphics-base-v1.1.h"
@@ -334,7 +336,7 @@
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
         const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile,
-        int streamUseCase, int timestampBase) {
+        int streamUseCase, int timestampBase, int mirrorMode) {
     // bufferProducer must be non-null
     if (gbp == nullptr) {
         String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
@@ -461,6 +463,13 @@
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
+    if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
+            mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
+        String8 msg = String8::format("Camera %s: invalid mirroring mode %d",
+                logicalCameraId.string(), mirrorMode);
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
 
     if (!isStreamInfoValid) {
         streamInfo.width = width;
@@ -472,6 +481,7 @@
         streamInfo.dynamicRangeProfile = dynamicRangeProfile;
         streamInfo.streamUseCase = streamUseCase;
         streamInfo.timestampBase = timestampBase;
+        streamInfo.mirrorMode = mirrorMode;
         return binder::Status::ok();
     }
     if (width != streamInfo.width) {
@@ -514,6 +524,296 @@
 
 void mapStreamInfo(const OutputStreamInfo &streamInfo,
             camera3::camera_stream_rotation_t rotation, String8 physicalId,
+            int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
+    if (stream == nullptr) {
+        return;
+    }
+
+    stream->streamType = aidl::android::hardware::camera::device::StreamType::OUTPUT;
+    stream->width = streamInfo.width;
+    stream->height = streamInfo.height;
+    stream->format = AidlCamera3Device::mapToAidlPixelFormat(streamInfo.format);
+    auto u = streamInfo.consumerUsage;
+    camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
+    stream->usage = AidlCamera3Device::mapToAidlConsumerUsage(u);
+    stream->dataSpace = AidlCamera3Device::mapToAidlDataspace(streamInfo.dataSpace);
+    stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
+    stream->id = -1; // Invalid stream id
+    stream->physicalCameraId = std::string(physicalId.string());
+    stream->bufferSize = 0;
+    stream->groupId = groupId;
+    stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
+    size_t idx = 0;
+    using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
+    for (auto mode : streamInfo.sensorPixelModesUsed) {
+        stream->sensorPixelModesUsed[idx++] =
+                static_cast<SensorPixelMode>(mode);
+    }
+    using DynamicRangeProfile =
+            aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
+    stream->dynamicRangeProfile = static_cast<DynamicRangeProfile>(streamInfo.dynamicRangeProfile);
+    using StreamUseCases =
+            aidl::android::hardware::camera::metadata::ScalerAvailableStreamUseCases;
+    stream->useCase = static_cast<StreamUseCases>(streamInfo.streamUseCase);
+}
+
+status_t
+convertAidlToHidl38StreamCombination(
+        const aidl::android::hardware::camera::device::StreamConfiguration &aidl,
+        hardware::camera::device::V3_8::StreamConfiguration &hidl) {
+    hidl.operationMode =
+        static_cast<hardware::camera::device::V3_2::StreamConfigurationMode>(aidl.operationMode);
+    if (aidl.streamConfigCounter < 0) {
+        return BAD_VALUE;
+    }
+    hidl.streamConfigCounter = static_cast<uint32_t>(aidl.streamConfigCounter);
+    hidl.multiResolutionInputImage = aidl.multiResolutionInputImage;
+    hidl.sessionParams = aidl.sessionParams.metadata;
+    hidl.streams.resize(aidl.streams.size());
+    size_t i = 0;
+    for (const auto &stream : aidl.streams) {
+        //hidlv3_8
+        hidl.streams[i].dynamicRangeProfile =
+                static_cast<
+                        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>
+                                (stream.dynamicRangeProfile);
+        hidl.streams[i].useCase =
+                static_cast<
+                        CameraMetadataEnumAndroidScalerAvailableStreamUseCases>
+                                (stream.useCase);
+
+        // hidl v3_7
+        hidl.streams[i].v3_7.groupId = stream.groupId;
+        hidl.streams[i].v3_7.sensorPixelModesUsed.resize(stream.sensorPixelModesUsed.size());
+        size_t j = 0;
+        for (const auto &mode : stream.sensorPixelModesUsed) {
+            hidl.streams[i].v3_7.sensorPixelModesUsed[j] =
+                    static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+            j++;
+        }
+
+        //hidl v3_4
+        hidl.streams[i].v3_7.v3_4.physicalCameraId = stream.physicalCameraId;
+
+        if (stream.bufferSize < 0) {
+            return BAD_VALUE;
+        }
+        hidl.streams[i].v3_7.v3_4.bufferSize = static_cast<uint32_t>(stream.bufferSize);
+
+        // hild v3_2
+        hidl.streams[i].v3_7.v3_4.v3_2.id = stream.id;
+        hidl.streams[i].v3_7.v3_4.v3_2.format =
+                static_cast<hardware::graphics::common::V1_0::PixelFormat>(stream.format);
+
+        if (stream.width < 0 || stream.height < 0) {
+            return BAD_VALUE;
+        }
+        hidl.streams[i].v3_7.v3_4.v3_2.width = static_cast<uint32_t>(stream.width);
+        hidl.streams[i].v3_7.v3_4.v3_2.height = static_cast<uint32_t>(stream.height);
+        hidl.streams[i].v3_7.v3_4.v3_2.usage =
+                static_cast<hardware::camera::device::V3_2::BufferUsageFlags>(stream.usage);
+        hidl.streams[i].v3_7.v3_4.v3_2.streamType =
+                static_cast<hardware::camera::device::V3_2::StreamType>(stream.streamType);
+        hidl.streams[i].v3_7.v3_4.v3_2.dataSpace =
+                static_cast<hardware::camera::device::V3_2::DataspaceFlags>(stream.dataSpace);
+        hidl.streams[i].v3_7.v3_4.v3_2.rotation =
+                static_cast<hardware::camera::device::V3_2::StreamRotation>(stream.rotation);
+        i++;
+    }
+    return OK;
+}
+
+binder::Status
+convertToHALStreamCombination(
+        const SessionConfiguration& sessionConfiguration,
+        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+        aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
+        bool overrideForPerfClass, bool *earlyExit) {
+    using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
+    auto operatingMode = sessionConfiguration.getOperatingMode();
+    binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (earlyExit == nullptr) {
+        String8 msg("earlyExit nullptr");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+    *earlyExit = false;
+    auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
+            static_cast<camera_stream_configuration_mode_t> (operatingMode),
+            /*out*/ &streamConfiguration.operationMode);
+    if (ret != OK) {
+        String8 msg = String8::format(
+            "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
+            logicalCameraId.string(), operatingMode, strerror(-ret), ret);
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                msg.string());
+    }
+
+    bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
+            (sessionConfiguration.getInputHeight() > 0) &&
+            (sessionConfiguration.getInputFormat() > 0);
+    auto outputConfigs = sessionConfiguration.getOutputConfigurations();
+    size_t streamCount = outputConfigs.size();
+    streamCount = isInputValid ? streamCount + 1 : streamCount;
+    streamConfiguration.streams.resize(streamCount);
+    size_t streamIdx = 0;
+    if (isInputValid) {
+        std::vector<SensorPixelMode> defaultSensorPixelModes;
+        defaultSensorPixelModes.resize(1);
+        defaultSensorPixelModes[0] =
+                static_cast<SensorPixelMode>(ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
+        aidl::android::hardware::camera::device::Stream stream;
+        stream.id = 0;
+        stream.streamType =  aidl::android::hardware::camera::device::StreamType::INPUT;
+        stream.width = static_cast<uint32_t> (sessionConfiguration.getInputWidth());
+        stream.height =  static_cast<uint32_t> (sessionConfiguration.getInputHeight());
+        stream.format =
+                AidlCamera3Device::AidlCamera3Device::mapToAidlPixelFormat(
+                        sessionConfiguration.getInputFormat());
+        stream.usage = static_cast<aidl::android::hardware::graphics::common::BufferUsage>(0);
+        stream.dataSpace =
+              static_cast<aidl::android::hardware::graphics::common::Dataspace>(
+                      HAL_DATASPACE_UNKNOWN);
+        stream.rotation = aidl::android::hardware::camera::device::StreamRotation::ROTATION_0;
+        stream.bufferSize = 0;
+        stream.groupId = -1;
+        stream.sensorPixelModesUsed = defaultSensorPixelModes;
+        streamConfiguration.streams[streamIdx++] = stream;
+        streamConfiguration.multiResolutionInputImage =
+                sessionConfiguration.inputIsMultiResolution();
+    }
+
+    for (const auto &it : outputConfigs) {
+        const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
+            it.getGraphicBufferProducers();
+        bool deferredConsumer = it.isDeferred();
+        String8 physicalCameraId = String8(it.getPhysicalCameraId());
+
+        int dynamicRangeProfile = it.getDynamicRangeProfile();
+        std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
+        const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
+                overrideForPerfClass);
+        const CameraMetadata &metadataChosen =
+                physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
+
+        size_t numBufferProducers = bufferProducers.size();
+        bool isStreamInfoValid = false;
+        int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
+        OutputStreamInfo streamInfo;
+
+        res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
+        if (!res.isOk()) {
+            return res;
+        }
+        res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
+                logicalCameraId);
+        if (!res.isOk()) {
+            return res;
+        }
+
+        int streamUseCase = it.getStreamUseCase();
+        int timestampBase = it.getTimestampBase();
+        int mirrorMode = it.getMirrorMode();
+        if (deferredConsumer) {
+            streamInfo.width = it.getWidth();
+            streamInfo.height = it.getHeight();
+            streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+            streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
+            auto surfaceType = it.getSurfaceType();
+            streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
+            if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
+                streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
+            }
+            streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
+            if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
+                    streamInfo.format, streamInfo.width,
+                    streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
+                    &streamInfo.sensorPixelModesUsed) != OK) {
+                        ALOGE("%s: Deferred surface sensor pixel modes not valid",
+                                __FUNCTION__);
+                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                                "Deferred surface sensor pixel modes not valid");
+            }
+            streamInfo.streamUseCase = streamUseCase;
+            mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
+                    &streamConfiguration.streams[streamIdx++]);
+            isStreamInfoValid = true;
+
+            if (numBufferProducers == 0) {
+                continue;
+            }
+        }
+
+        for (auto& bufferProducer : bufferProducers) {
+            sp<Surface> surface;
+            res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
+                    logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
+                    streamUseCase, timestampBase, mirrorMode);
+
+            if (!res.isOk())
+                return res;
+
+            if (!isStreamInfoValid) {
+                bool isDepthCompositeStream =
+                        camera3::DepthCompositeStream::isDepthCompositeStream(surface);
+                bool isHeicCompositeStream =
+                        camera3::HeicCompositeStream::isHeicCompositeStream(surface);
+                if (isDepthCompositeStream || isHeicCompositeStream) {
+                    // We need to take in to account that composite streams can have
+                    // additional internal camera streams.
+                    std::vector<OutputStreamInfo> compositeStreams;
+                    if (isDepthCompositeStream) {
+                      // TODO: Take care of composite streams.
+                        ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
+                                deviceInfo, &compositeStreams);
+                    } else {
+                        ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
+                            deviceInfo, &compositeStreams);
+                    }
+                    if (ret != OK) {
+                        String8 msg = String8::format(
+                                "Camera %s: Failed adding composite streams: %s (%d)",
+                                logicalCameraId.string(), strerror(-ret), ret);
+                        ALOGE("%s: %s", __FUNCTION__, msg.string());
+                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                    }
+
+                    if (compositeStreams.size() == 0) {
+                        // No internal streams means composite stream not
+                        // supported.
+                        *earlyExit = true;
+                        return binder::Status::ok();
+                    } else if (compositeStreams.size() > 1) {
+                        streamCount += compositeStreams.size() - 1;
+                        streamConfiguration.streams.resize(streamCount);
+                    }
+
+                    for (const auto& compositeStream : compositeStreams) {
+                        mapStreamInfo(compositeStream,
+                                static_cast<camera_stream_rotation_t> (it.getRotation()),
+                                physicalCameraId, groupId,
+                                &streamConfiguration.streams[streamIdx++]);
+                    }
+                } else {
+                    mapStreamInfo(streamInfo,
+                            static_cast<camera_stream_rotation_t> (it.getRotation()),
+                            physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
+                }
+                isStreamInfoValid = true;
+            }
+        }
+    }
+    return binder::Status::ok();
+}
+
+void mapStreamInfo(const OutputStreamInfo &streamInfo,
+            camera3::camera_stream_rotation_t rotation, String8 physicalId,
             int32_t groupId, hardware::camera::device::V3_8::Stream *stream /*out*/) {
     if (stream == nullptr) {
         return;
@@ -625,176 +925,22 @@
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         hardware::camera::device::V3_8::StreamConfiguration &streamConfiguration,
         bool overrideForPerfClass, bool *earlyExit) {
-
-    auto operatingMode = sessionConfiguration.getOperatingMode();
-    binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
-    if (!res.isOk()) {
-        return res;
+    aidl::android::hardware::camera::device::StreamConfiguration aidlStreamConfiguration;
+    auto ret = convertToHALStreamCombination(sessionConfiguration, logicalCameraId, deviceInfo,
+            getMetadata, physicalCameraIds, aidlStreamConfiguration, overrideForPerfClass,
+            earlyExit);
+    if (!ret.isOk()) {
+        return ret;
+    }
+    if (earlyExit != nullptr && *earlyExit) {
+        return binder::Status::ok();
     }
 
-    if (earlyExit == nullptr) {
-        String8 msg("earlyExit nullptr");
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-    }
-    *earlyExit = false;
-    auto ret = HidlCamera3Device::mapToStreamConfigurationMode(
-            static_cast<camera_stream_configuration_mode_t> (operatingMode),
-            /*out*/ &streamConfiguration.operationMode);
-    if (ret != OK) {
-        String8 msg = String8::format(
-            "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
-            logicalCameraId.string(), operatingMode, strerror(-ret), ret);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+    if (convertAidlToHidl38StreamCombination(aidlStreamConfiguration, streamConfiguration) != OK) {
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                msg.string());
+                "Invalid AIDL->HIDL3.8 conversion");
     }
 
-    bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
-            (sessionConfiguration.getInputHeight() > 0) &&
-            (sessionConfiguration.getInputFormat() > 0);
-    auto outputConfigs = sessionConfiguration.getOutputConfigurations();
-    size_t streamCount = outputConfigs.size();
-    streamCount = isInputValid ? streamCount + 1 : streamCount;
-    streamConfiguration.streams.resize(streamCount);
-    size_t streamIdx = 0;
-    if (isInputValid) {
-        hardware::hidl_vec<CameraMetadataEnumAndroidSensorPixelMode> defaultSensorPixelModes;
-        defaultSensorPixelModes.resize(1);
-        defaultSensorPixelModes[0] =
-                static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
-                        ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
-        streamConfiguration.streams[streamIdx++].v3_7 = {{{/*streamId*/0,
-                hardware::camera::device::V3_2::StreamType::INPUT,
-                static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
-                static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
-                HidlCamera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
-                /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
-                hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
-                /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
-        streamConfiguration.multiResolutionInputImage =
-                sessionConfiguration.inputIsMultiResolution();
-    }
-
-    for (const auto &it : outputConfigs) {
-        const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
-            it.getGraphicBufferProducers();
-        bool deferredConsumer = it.isDeferred();
-        String8 physicalCameraId = String8(it.getPhysicalCameraId());
-
-        int dynamicRangeProfile = it.getDynamicRangeProfile();
-        std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
-        const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
-                overrideForPerfClass);
-        const CameraMetadata &metadataChosen =
-                physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
-
-        size_t numBufferProducers = bufferProducers.size();
-        bool isStreamInfoValid = false;
-        int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
-        OutputStreamInfo streamInfo;
-
-        res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
-        if (!res.isOk()) {
-            return res;
-        }
-        res = checkPhysicalCameraId(physicalCameraIds, physicalCameraId,
-                logicalCameraId);
-        if (!res.isOk()) {
-            return res;
-        }
-
-        int streamUseCase = it.getStreamUseCase();
-        int timestampBase = it.getTimestampBase();
-        if (deferredConsumer) {
-            streamInfo.width = it.getWidth();
-            streamInfo.height = it.getHeight();
-            streamInfo.format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-            streamInfo.dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN;
-            auto surfaceType = it.getSurfaceType();
-            streamInfo.consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE;
-            if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
-                streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
-            }
-            streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
-            if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
-                    streamInfo.format, streamInfo.width,
-                    streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
-                    &streamInfo.sensorPixelModesUsed) != OK) {
-                        ALOGE("%s: Deferred surface sensor pixel modes not valid",
-                                __FUNCTION__);
-                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                                "Deferred surface sensor pixel modes not valid");
-            }
-            streamInfo.streamUseCase = streamUseCase;
-            mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
-                    &streamConfiguration.streams[streamIdx++]);
-            isStreamInfoValid = true;
-
-            if (numBufferProducers == 0) {
-                continue;
-            }
-        }
-
-        for (auto& bufferProducer : bufferProducers) {
-            sp<Surface> surface;
-            res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
-                    logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
-                    streamUseCase, timestampBase);
-
-            if (!res.isOk())
-                return res;
-
-            if (!isStreamInfoValid) {
-                bool isDepthCompositeStream =
-                        camera3::DepthCompositeStream::isDepthCompositeStream(surface);
-                bool isHeicCompositeStream =
-                        camera3::HeicCompositeStream::isHeicCompositeStream(surface);
-                if (isDepthCompositeStream || isHeicCompositeStream) {
-                    // We need to take in to account that composite streams can have
-                    // additional internal camera streams.
-                    std::vector<OutputStreamInfo> compositeStreams;
-                    if (isDepthCompositeStream) {
-                      // TODO: Take care of composite streams.
-                        ret = camera3::DepthCompositeStream::getCompositeStreamInfo(streamInfo,
-                                deviceInfo, &compositeStreams);
-                    } else {
-                        ret = camera3::HeicCompositeStream::getCompositeStreamInfo(streamInfo,
-                            deviceInfo, &compositeStreams);
-                    }
-                    if (ret != OK) {
-                        String8 msg = String8::format(
-                                "Camera %s: Failed adding composite streams: %s (%d)",
-                                logicalCameraId.string(), strerror(-ret), ret);
-                        ALOGE("%s: %s", __FUNCTION__, msg.string());
-                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-                    }
-
-                    if (compositeStreams.size() == 0) {
-                        // No internal streams means composite stream not
-                        // supported.
-                        *earlyExit = true;
-                        return binder::Status::ok();
-                    } else if (compositeStreams.size() > 1) {
-                        streamCount += compositeStreams.size() - 1;
-                        streamConfiguration.streams.resize(streamCount);
-                    }
-
-                    for (const auto& compositeStream : compositeStreams) {
-                        mapStreamInfo(compositeStream,
-                                static_cast<camera_stream_rotation_t> (it.getRotation()),
-                                physicalCameraId, groupId,
-                                &streamConfiguration.streams[streamIdx++]);
-                    }
-                } else {
-                    mapStreamInfo(streamInfo,
-                            static_cast<camera_stream_rotation_t> (it.getRotation()),
-                            physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
-                }
-                isStreamInfoValid = true;
-            }
-        }
-    }
     return binder::Status::ok();
 }
 
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 3dcbdbc..7027dfe 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -22,6 +22,7 @@
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
 #include <android/hardware/camera/device/3.8/types.h>
+#include <aidl/android/hardware/camera/device/ICameraDevice.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
@@ -98,7 +99,7 @@
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
         const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed,  int dynamicRangeProfile,
-        int streamUseCase, int timestampBase);
+        int streamUseCase, int timestampBase, int mirrorMode);
 
 void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
         camera3::camera_stream_rotation_t rotation, String8 physicalId, int32_t groupId,
@@ -115,6 +116,10 @@
 
 bool isStreamUseCaseSupported(int streamUseCase, const CameraMetadata &deviceInfo);
 
+void mapStreamInfo(const OutputStreamInfo &streamInfo,
+        camera3::camera_stream_rotation_t rotation, String8 physicalId,
+        int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/);
+
 // Check that the physicalCameraId passed in is spported by the camera
 // device.
 binder::Status checkPhysicalCameraId(
@@ -145,6 +150,14 @@
         hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37,
         const hardware::camera::device::V3_8::StreamConfiguration &streamConfigV38);
 
+binder::Status
+convertToHALStreamCombination(
+    const SessionConfiguration& sessionConfiguration,
+    const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+    metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+    aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
+    bool overrideForPerfClass, bool *earlyExit);
+
 // Utility function to convert a V3_7::StreamConfiguration to
 // V3_4::StreamConfiguration. Return false if the original V3_7 configuration cannot
 // be used by older version HAL.
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index d50f8d5..57be435 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -442,11 +442,11 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
-    if (!mProcessInfo->isValidPid(pid)) {
+    if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
         pid_t callingPid = IPCThreadState::self()->getCallingPid();
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
-        ALOGW("%s called with untrusted pid %d, using calling pid %d, uid %d", __FUNCTION__,
-                pid, callingPid, callingUid);
+        ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
+                __FUNCTION__, pid, uid, callingPid, callingUid);
         pid = callingPid;
         uid = callingUid;
     }
@@ -500,7 +500,7 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
-    if (!mProcessInfo->isValidPid(pid)) {
+    if (!mProcessInfo->isPidTrusted(pid)) {
         pid_t callingPid = IPCThreadState::self()->getCallingPid();
         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                 pid, callingPid);
@@ -568,7 +568,7 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
-    if (checkValid && !mProcessInfo->isValidPid(pid)) {
+    if (checkValid && !mProcessInfo->isPidTrusted(pid)) {
         pid_t callingPid = IPCThreadState::self()->getCallingPid();
         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                 pid, callingPid);
@@ -623,7 +623,7 @@
     Vector<std::shared_ptr<IResourceManagerClient>> clients;
     {
         Mutex::Autolock lock(mLock);
-        if (!mProcessInfo->isValidPid(callingPid)) {
+        if (!mProcessInfo->isPidTrusted(callingPid)) {
             pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
             ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
                     callingPid, actualCallingPid);
@@ -866,7 +866,7 @@
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
-    if (!mProcessInfo->isValidPid(pid)) {
+    if (!mProcessInfo->isPidTrusted(pid)) {
         pid_t callingPid = IPCThreadState::self()->getCallingPid();
         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                 pid, callingPid);
@@ -898,7 +898,7 @@
     Vector<std::shared_ptr<IResourceManagerClient>> clients;
     {
         Mutex::Autolock lock(mLock);
-        if (!mProcessInfo->isValidPid(pid)) {
+        if (!mProcessInfo->isPidTrusted(pid)) {
             pid_t callingPid = IPCThreadState::self()->getCallingPid();
             ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                     pid, callingPid);
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index 6690b16..8f25ee6 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -71,7 +71,8 @@
         return true;
     }
 
-    virtual bool isValidPid(int /* pid */) { return true; }
+    virtual bool isPidTrusted(int /* pid */) { return true; }
+    virtual bool isPidUidTrusted(int /* pid */, int /* uid */) { return true; }
     virtual bool overrideProcessInfo(int /* pid */, int /*procState*/, int /*oomScore*/) {
         return true;
     }
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 1624477..5bf44ce 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -46,7 +46,11 @@
         return true;
     }
 
-    virtual bool isValidPid(int /* pid */) {
+    virtual bool isPidTrusted(int /* pid */) {
+        return true;
+    }
+
+    virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
         return true;
     }