Merge "codec2: libgav1 integration part 1"
diff --git a/apex/manifest.json b/apex/manifest.json
index 03b9dd0..3011ee8 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media",
-  "version": 220000000
+  "version": 290000000
 }
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 58ce868..83a5178 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media.swcodec",
-  "version": 220000000
+  "version": 290000000
 }
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 529c167..a43d707 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -31,6 +31,17 @@
 
 #include "ACameraCaptureSession.inc"
 
+#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
+    if (!remoteRet.isOk()) { \
+        ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
+                  remoteRet.description().c_str()); \
+        return ACAMERA_ERROR_UNKNOWN; \
+    } \
+    if (status != Status::NO_ERROR) { \
+        ALOGE("%s: %s call failed", __FUNCTION__, callName); \
+        return utils::convertFromHidl(status); \
+    }
+
 using namespace android;
 
 namespace android {
@@ -151,7 +162,7 @@
         return ACAMERA_ERROR_CAMERA_DISCONNECTED;
     }
     CameraMetadata rawRequest;
-    Status status = Status::NO_ERROR;
+    Status status = Status::UNKNOWN_ERROR;
     auto remoteRet = mRemote->createDefaultRequest(
         utils::convertToHidl(templateId),
         [&status, &rawRequest](auto s, const hidl_vec<uint8_t> &metadata) {
@@ -161,14 +172,7 @@
                 ALOGE("%s: Couldn't create default request", __FUNCTION__);
             }
         });
-    if (!remoteRet.isOk()) {
-        ALOGE("%s: Transaction error while trying to create default request %s", __FUNCTION__,
-              remoteRet.description().c_str());
-        return ACAMERA_ERROR_UNKNOWN;
-    }
-    if (status != Status::NO_ERROR) {
-        return utils::convertFromHidl(status);
-    }
+    CHECK_TRANSACTION_AND_RET(remoteRet, status, "createDefaultRequest()")
     ACaptureRequest* outReq = new ACaptureRequest();
     outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
     if (physicalCameraIdList != nullptr) {
@@ -243,20 +247,15 @@
     }
 
     bool configSupported = false;
-    Status status = Status::NO_ERROR;
+    Status status = Status::UNKNOWN_ERROR;
     auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
         [&status, &configSupported](auto s, auto supported) {
             status = s;
             configSupported = supported;
         });
 
-    if (status == Status::INVALID_OPERATION) {
-        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
-    } else if (!remoteRet.isOk()) {
-        return ACAMERA_ERROR_UNKNOWN;
-    } else {
-        return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
-    }
+    CHECK_TRANSACTION_AND_RET(remoteRet, status, "isSessionConfigurationSupported()");
+    return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
 }
 
 static void addMetadataToPhysicalCameraSettings(const CameraMetadata *metadata,
@@ -525,16 +524,13 @@
         mRepeatingSequenceId = REQUEST_ID_NONE;
 
         int64_t lastFrameNumber;
-        Status status = Status::NO_ERROR;
+        Status status = Status::UNKNOWN_ERROR;
         auto remoteRet = mRemote->cancelRepeatingRequest(
                 [&status, &lastFrameNumber](Status s, auto frameNumber) {
                     status = s;
                     lastFrameNumber = frameNumber;
                 });
-        if (!remoteRet.isOk() || status != Status::NO_ERROR) {
-            ALOGE("%s: Unable to cancel active repeating request", __FUNCTION__);
-            return utils::convertFromHidl(status);
-        }
+        CHECK_TRANSACTION_AND_RET(remoteRet, status, "cancelRepeatingRequest()");
         checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
     }
     return ACAMERA_OK;
@@ -582,15 +578,12 @@
     }
 
     int64_t lastFrameNumber;
-    Status status;
+    Status status = Status::UNKNOWN_ERROR;
     auto remoteRet = mRemote->flush([&status, &lastFrameNumber](auto s, auto frameNumber) {
                                         status = s;
                                         lastFrameNumber = frameNumber;
                                     });
-    if (!remoteRet.isOk() || status != Status::NO_ERROR) {
-        ALOGE("%s: Abort captures failed", __FUNCTION__);
-        return utils::convertFromHidl(status);
-    }
+    CHECK_TRANSACTION_AND_RET(remoteRet, status, "flush()")
     if (mRepeatingSequenceId != REQUEST_ID_NONE) {
         checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
     }
@@ -611,10 +604,7 @@
     }
 
     auto remoteRet = mRemote->waitUntilIdle();
-    if (!remoteRet.isOk()) {
-        ALOGE("%s: Transaction waitUntilIdle failed", __FUNCTION__);
-        return utils::convertFromHidl(remoteRet);
-    }
+    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "waitUntilIdle()")
     return ACAMERA_OK;
 }
 
@@ -689,34 +679,25 @@
     mIdle = true;
 
     auto remoteRet = mRemote->beginConfigure();
-    if (!remoteRet.isOk()|| remoteRet != Status::NO_ERROR) {
-        ALOGE("Camera device %s begin configure failed", getId());
-        return utils::convertFromHidl(remoteRet);
-    }
+    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "beginConfigure()")
 
     // delete to-be-deleted streams
     for (auto streamId : deleteList) {
         remoteRet = mRemote->deleteStream(streamId);
-        if (!remoteRet.isOk() || remoteRet != Status::NO_ERROR) {
-            ALOGE("Camera device %s failed to remove stream %d", getId(), streamId);
-            return utils::convertFromHidl(remoteRet);
-        }
+        CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "deleteStream()")
         mConfiguredOutputs.erase(streamId);
     }
 
     // add new streams
     for (auto outputPair : addSet) {
         int streamId;
-        Status status;
+        Status status = Status::UNKNOWN_ERROR;
         auto ret = mRemote->createStream(outputPair.second,
                                          [&status, &streamId](Status s, auto stream_id) {
                                              status = s;
                                              streamId = stream_id;
                                          });
-        if (!remoteRet.isOk() || status != Status::NO_ERROR) {
-            ALOGE("Camera device %s failed to create stream", getId());
-            return utils::convertFromHidl(status);
-        }
+        CHECK_TRANSACTION_AND_RET(ret, status, "createStream()")
         mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
     }
 
@@ -729,11 +710,8 @@
         params.unlock(params_metadata);
     }
     remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE, hidlParams);
-    if (!remoteRet.isOk()) {
-        ALOGE("Transaction error: endConfigure failed %s", remoteRet.description().c_str());
-    }
-
-    return utils::convertFromHidl(remoteRet);
+    CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "endConfigure()")
+    return ACAMERA_OK;
 }
 
 void
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 37de30a..7ab0124 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include <mutex>
 #include <string>
+#include <variant>
 #include <vector>
 #include <stdio.h>
 #include <stdio.h>
@@ -49,6 +50,7 @@
 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
 
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ConfiguredWindows = std::set<native_handle_t *>;
 
 class CameraHelper {
    public:
@@ -60,9 +62,12 @@
         const char* physicalCameraId;
         native_handle_t* anw;
     };
-    int initCamera(native_handle_t* imgReaderAnw,
+
+    // Retaining the error code in case the caller needs to analyze it.
+    std::variant<int, ConfiguredWindows> initCamera(native_handle_t* imgReaderAnw,
             const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
             bool usePhysicalSettings) {
+        ConfiguredWindows configuredWindows;
         if (imgReaderAnw == nullptr) {
             ALOGE("Cannot initialize camera before image reader get initialized.");
             return -1;
@@ -78,7 +83,7 @@
         ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
         if (ret != AMEDIA_OK || mDevice == nullptr) {
             ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
-            return -1;
+            return ret;
         }
 
         // Create capture session
@@ -97,8 +102,9 @@
             ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
             return ret;
         }
-
+        configuredWindows.insert(mImgReaderAnw);
         std::vector<const char*> idPointerList;
+        std::set<const native_handle_t*> physicalStreamMap;
         for (auto& physicalStream : physicalImgReaders) {
             ACaptureSessionOutput* sessionOutput = nullptr;
             ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@@ -112,21 +118,25 @@
                 ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
                 return ret;
             }
-            mExtraOutputs.push_back(sessionOutput);
+            ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
+            if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
+                ALOGW("ACameraDevice_isSessionConfigurationSupported failed, ret=%d camera id %s",
+                      ret, mCameraId);
+                ACaptureSessionOutputContainer_remove(mOutputs, sessionOutput);
+                ACaptureSessionOutput_free(sessionOutput);
+                continue;
+            }
+            configuredWindows.insert(physicalStream.anw);
             // Assume that at most one physical stream per physical camera.
             mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
             idPointerList.push_back(physicalStream.physicalCameraId);
+            physicalStreamMap.insert(physicalStream.anw);
+            mSessionPhysicalOutputs.push_back(sessionOutput);
         }
         ACameraIdList cameraIdList;
         cameraIdList.numCameras = idPointerList.size();
         cameraIdList.cameraIds = idPointerList.data();
 
-        ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
-        if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
-            ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret);
-            return ret;
-        }
-
         ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
         if (ret != AMEDIA_OK) {
             ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -157,6 +167,10 @@
         }
 
         for (auto& physicalStream : physicalImgReaders) {
+            if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
+                ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
+                continue;
+            }
             ACameraOutputTarget* outputTarget = nullptr;
             ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
             if (ret != AMEDIA_OK) {
@@ -168,11 +182,11 @@
                 ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
                 return ret;
             }
-            mReqExtraOutputs.push_back(outputTarget);
+            mReqPhysicalOutputs.push_back(outputTarget);
         }
 
         mIsCameraReady = true;
-        return 0;
+        return configuredWindows;
     }
 
 
@@ -184,10 +198,10 @@
             ACameraOutputTarget_free(mReqImgReaderOutput);
             mReqImgReaderOutput = nullptr;
         }
-        for (auto& outputTarget : mReqExtraOutputs) {
+        for (auto& outputTarget : mReqPhysicalOutputs) {
             ACameraOutputTarget_free(outputTarget);
         }
-        mReqExtraOutputs.clear();
+        mReqPhysicalOutputs.clear();
         if (mStillRequest) {
             ACaptureRequest_free(mStillRequest);
             mStillRequest = nullptr;
@@ -201,10 +215,10 @@
             ACaptureSessionOutput_free(mImgReaderOutput);
             mImgReaderOutput = nullptr;
         }
-        for (auto& extraOutput : mExtraOutputs) {
+        for (auto& extraOutput : mSessionPhysicalOutputs) {
             ACaptureSessionOutput_free(extraOutput);
         }
-        mExtraOutputs.clear();
+        mSessionPhysicalOutputs.clear();
         if (mOutputs) {
             ACaptureSessionOutputContainer_free(mOutputs);
             mOutputs = nullptr;
@@ -262,13 +276,13 @@
     // Capture session
     ACaptureSessionOutputContainer* mOutputs = nullptr;
     ACaptureSessionOutput* mImgReaderOutput = nullptr;
-    std::vector<ACaptureSessionOutput*> mExtraOutputs;
+    std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
 
     ACameraCaptureSession* mSession = nullptr;
     // Capture request
     ACaptureRequest* mStillRequest = nullptr;
     ACameraOutputTarget* mReqImgReaderOutput = nullptr;
-    std::vector<ACameraOutputTarget*> mReqExtraOutputs;
+    std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
 
     bool mIsCameraReady = false;
     const char* mCameraId;
@@ -581,9 +595,11 @@
         }
 
         CameraHelper cameraHelper(id, mCameraManager);
-        ret = cameraHelper.initCamera(testCase.getNativeWindow(),
-                {}/*physicalImageReaders*/, false/*usePhysicalSettings*/);
-        if (ret < 0) {
+        std::variant<int, ConfiguredWindows> retInit =
+                cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
+                                        false/*usePhysicalSettings*/);
+        int *retp = std::get_if<int>(&retInit);
+        if (retp) {
             ALOGE("Unable to initialize camera helper");
             return false;
         }
@@ -751,10 +767,15 @@
         physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
         physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
 
-        int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(),
-                physicalImgReaderInfo, usePhysicalSettings);
-        ASSERT_EQ(ret, 0);
-
+        std::variant<int, ConfiguredWindows> retInit =
+                cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
+                                        usePhysicalSettings);
+        int *retp = std::get_if<int>(&retInit);
+        ASSERT_EQ(retp, nullptr);
+        ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
+        ASSERT_NE(configuredWindowsp, nullptr);
+        ASSERT_LE(configuredWindowsp->size(), testCases.size());
+        int ret = 0;
         if (!cameraHelper.isCameraReady()) {
             ALOGW("Camera is not ready after successful initialization. It's either due to camera "
                   "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
@@ -776,9 +797,15 @@
                 break;
             }
         }
-        ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
-        ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
-        ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+        for(auto &testCase : testCases) {
+            auto it = configuredWindowsp->find(testCase->getNativeWindow());
+            if (it == configuredWindowsp->end()) {
+                continue;
+            }
+            ALOGI("Testing window %p", testCase->getNativeWindow());
+            ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
+        }
+
         ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
 
         ACameraMetadata_free(staticMetadata);
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 077a91f..1cfdc19 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -508,7 +508,7 @@
                .limitTo(D::ENCODER & D::VIDEO));
     // convert to timestamp base
     add(ConfigMapper(KEY_I_FRAME_INTERVAL, C2_PARAMKEY_SYNC_FRAME_INTERVAL, "value")
-        .withMapper([](C2Value v) -> C2Value {
+        .withMappers([](C2Value v) -> C2Value {
             // convert from i32 to float
             int32_t i32Value;
             float fpValue;
@@ -518,6 +518,12 @@
                 return int64_t(c2_min(1000000 * fpValue + 0.5, (double)INT64_MAX));
             }
             return C2Value();
+        }, [](C2Value v) -> C2Value {
+            int64_t i64;
+            if (v.get(&i64)) {
+                return float(i64) / 1000000;
+            }
+            return C2Value();
         }));
     // remove when codecs switch to proper coding.gop (add support for calculating gop)
     deprecated(ConfigMapper("i-frame-period", "coding.gop", "intra-period")
@@ -711,7 +717,7 @@
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -722,7 +728,7 @@
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -733,7 +739,7 @@
 
     // convert to 0-1 (%) and add default
     add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -744,7 +750,7 @@
 
     // convert to compression type and add default
     add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -755,7 +761,7 @@
 
     // convert to dBFS and add default
     add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < 0) {
@@ -766,7 +772,7 @@
 
     // convert to effect type (these map to SDK values) and add default
     add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value")
-        .limitTo(D::AUDIO & D::DECODER)
+        .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
         .withMapper([](C2Value v) -> C2Value {
             int32_t value;
             if (!v.get(&value) || value < -1 || value > 8) {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1e7f9fa..02dc516 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1512,6 +1512,13 @@
     return aps->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
 }
 
+status_t AudioSystem::setRttEnabled(bool enabled)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setRttEnabled(enabled);
+}
+
 // ---------------------------------------------------------------------------
 
 int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index c548457..64f0aca 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -104,6 +104,7 @@
     GET_VOLUME_GROUP_FOR_ATTRIBUTES,
     SET_ALLOWED_CAPTURE_POLICY,
     MOVE_EFFECTS_TO_IO,
+    SET_RTT_ENABLED
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -1271,6 +1272,18 @@
         volumeGroup = static_cast<volume_group_t>(reply.readInt32());
         return NO_ERROR;
     }
+
+    virtual status_t setRttEnabled(bool enabled)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast<int32_t>(enabled));
+        status_t status = remote()->transact(SET_RTT_ENABLED, data, &reply);
+        if (status != NO_ERROR) {
+           return status;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1332,7 +1345,8 @@
         case REMOVE_UID_DEVICE_AFFINITY:
         case GET_OFFLOAD_FORMATS_A2DP:
         case LIST_AUDIO_VOLUME_GROUPS:
-        case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
+        case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
+        case SET_RTT_ENABLED: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -2347,6 +2361,14 @@
             return NO_ERROR;
         }
 
+        case SET_RTT_ENABLED: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            bool enabled = static_cast<bool>(data.readInt32());
+            status_t status = setRttEnabled(enabled);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 56c69f6..09e80b2 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -394,6 +394,8 @@
     static status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
                                                       volume_group_t &volumeGroup);
 
+    static status_t setRttEnabled(bool enabled);
+
     // ----------------------------------------------------------------------------
 
     class AudioVolumeGroupCallback : public RefBase
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 33ab1f9..32275cf 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -220,6 +220,8 @@
     virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
     virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
                                                        volume_group_t &volumeGroup) = 0;
+
+    virtual status_t setRttEnabled(bool enabled) = 0;
 };
 
 
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index b25f82e..b07f21d 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -322,6 +322,14 @@
         const struct audio_port_config *sinks,
         audio_patch_handle_t *patch) {
     if (mDevice == 0) return NO_INIT;
+    if (patch == nullptr) return BAD_VALUE;
+
+    if (*patch != AUDIO_PATCH_HANDLE_NONE) {
+        status_t status = releaseAudioPatch(*patch);
+        ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
+            __func__, status, *patch);
+    }
+
     hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
     HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
     HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index 80e8f3a..6dc46b7 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -625,8 +625,18 @@
 // convert: AnwBuffer -> GraphicBuffer
 // Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
 inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
-    native_handle_t* handle = t.nativeHandle == nullptr ?
-            nullptr : native_handle_clone(t.nativeHandle);
+    native_handle_t* handle = nullptr;
+
+    if (t.nativeHandle != nullptr) {
+        handle = native_handle_clone(t.nativeHandle);
+        if (handle == nullptr) {
+            ALOGE("Failed to clone handle: numFds=%d, data[0]=%d, data[1]=%d",
+                    t.nativeHandle->numFds,
+                    (t.nativeHandle->numFds > 0) ? t.nativeHandle->data[0] : -1,
+                    (t.nativeHandle->numFds > 1) ? t.nativeHandle->data[1] : -1);
+            return false;
+        }
+    }
 
     size_t const numInts = 12 + (handle ? handle->numInts : 0);
     int32_t* ints = new int32_t[numInts];
@@ -756,7 +766,12 @@
                 return true;
             }
             AnwBuffer anwBuffer;
-            anwBuffer.nativeHandle = t.nativeHandle;
+            // Explicitly get the native_handle_t* (in stead of assigning t.nativeHandle)
+            // so that we don't do an extra native_handle_clone() in this step, as the
+            // convertion to GraphicBuffer below will do a clone regardless.
+            // If we encounter an invalid handle, the convertTo() below would fail (while
+            // the assigning of hidl_handle would abort and cause a crash).
+            anwBuffer.nativeHandle = t.nativeHandle.getNativeHandle();
             anwBuffer.attr = t.attr.anwBuffer;
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
             if (!convertTo(graphicBuffer.get(), anwBuffer)) {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 5a58aa0..0f72c0d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -90,8 +90,11 @@
     ALOGV("resetDataSource");
 
     mHTTPService.clear();
-    mHttpSource.clear();
-    mDisconnected = false;
+    {
+        Mutex::Autolock _l_d(mDisconnectLock);
+        mHttpSource.clear();
+        mDisconnected = false;
+    }
     mUri.clear();
     mUriHeaders.clear();
     mSources.clear();
@@ -152,7 +155,10 @@
     ALOGV("setDataSource (source: %p)", source.get());
 
     resetDataSource();
-    mDataSource = source;
+    {
+        Mutex::Autolock _l_d(mDisconnectLock);
+        mDataSource = source;
+    }
     return OK;
 }
 
@@ -163,8 +169,12 @@
 
 status_t NuPlayer::GenericSource::initFromDataSource() {
     sp<IMediaExtractor> extractor;
-    CHECK(mDataSource != NULL);
-    sp<DataSource> dataSource = mDataSource;
+    sp<DataSource> dataSource;
+    {
+        Mutex::Autolock _l_d(mDisconnectLock);
+        dataSource = mDataSource;
+    }
+    CHECK(dataSource != NULL);
 
     mLock.unlock();
     // This might take long time if data source is not reliable.
@@ -359,6 +369,7 @@
 }
 
 void NuPlayer::GenericSource::onPrepareAsync() {
+    mDisconnectLock.lock();
     ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
 
     // delayed data source creation
@@ -372,20 +383,29 @@
             String8 contentType;
 
             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
-                mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
-                if (mHttpSource == NULL) {
+                sp<DataSource> httpSource;
+                mDisconnectLock.unlock();
+                httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
+                if (httpSource == NULL) {
                     ALOGE("Failed to create http source!");
                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
                     return;
                 }
+                mDisconnectLock.lock();
+
+                if (!mDisconnected) {
+                    mHttpSource = httpSource;
+                }
             }
 
             mLock.unlock();
+            mDisconnectLock.unlock();
             // This might take long time if connection has some issue.
             sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
                    mHTTPService, uri, &mUriHeaders, &contentType,
                    static_cast<HTTPBase *>(mHttpSource.get()));
             mLock.lock();
+            mDisconnectLock.lock();
             if (!mDisconnected) {
                 mDataSource = dataSource;
             }
@@ -428,6 +448,7 @@
 
         if (mDataSource == NULL) {
             ALOGE("Failed to create data source!");
+            mDisconnectLock.unlock();
             notifyPreparedAndCleanup(UNKNOWN_ERROR);
             return;
         }
@@ -437,6 +458,8 @@
         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
     }
 
+    mDisconnectLock.unlock();
+
     // For cached streaming cases, we need to wait for enough
     // buffering before reporting prepared.
     mIsStreaming = (mCachedSource != NULL);
@@ -503,9 +526,13 @@
 
 void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
     if (err != OK) {
-        mDataSource.clear();
+        {
+            Mutex::Autolock _l_d(mDisconnectLock);
+            mDataSource.clear();
+            mHttpSource.clear();
+        }
+
         mCachedSource.clear();
-        mHttpSource.clear();
 
         mBitrate = -1;
         mPrevBufferPercentage = -1;
@@ -547,7 +574,7 @@
 void NuPlayer::GenericSource::disconnect() {
     sp<DataSource> dataSource, httpSource;
     {
-        Mutex::Autolock _l(mLock);
+        Mutex::Autolock _l_d(mDisconnectLock);
         dataSource = mDataSource;
         httpSource = mHttpSource;
         mDisconnected = true;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 065cac1..4d1905d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -170,6 +170,7 @@
     sp<ABuffer> mGlobalTimedText;
 
     mutable Mutex mLock;
+    mutable Mutex mDisconnectLock; // Protects mDataSource, mHttpSource and mDisconnected
 
     sp<ALooper> mLooper;
 
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index cb87b55..b738fef 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -52,6 +52,7 @@
 
 OggWriter::OggWriter(int fd)
       : mFd(dup(fd)),
+        mHaveAllCodecSpecificData(false),
         mInitCheck(mFd < 0 ? NO_INIT : OK) {
     // empty
 }
@@ -115,17 +116,26 @@
 
     mSampleRate = sampleRate;
     uint32_t type;
-    const void *header_data;
-    size_t packet_size;
+    const void *header_data = NULL;
+    size_t packet_size = 0;
+
     if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
-        ALOGE("opus header not found");
-        return UNKNOWN_ERROR;
+        ALOGV("opus header not found in format");
+    } else if (header_data && packet_size) {
+        writeOggHeaderPackets((unsigned char *)header_data, packet_size);
+    } else {
+        ALOGD("ignoring incomplete opus header data in format");
     }
 
+    mSource = source;
+    return OK;
+}
+
+status_t OggWriter::writeOggHeaderPackets(unsigned char *buf, size_t size) {
     ogg_packet op;
     ogg_page og;
-    op.packet = (unsigned char *)header_data;
-    op.bytes = packet_size;
+    op.packet = buf;
+    op.bytes = size;
     op.b_o_s = 1;
     op.e_o_s = 0;
     op.granulepos = 0;
@@ -169,8 +179,8 @@
         write(mFd, og.body, og.body_len);
     }
 
-    mSource = source;
     free(comments);
+    mHaveAllCodecSpecificData = true;
     return OK;
 }
 
@@ -301,12 +311,35 @@
              && isCodecSpecific)
             || IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
                          buffer->range_length())) {
-            ALOGV("Drop codec specific info buffer");
+            if (mHaveAllCodecSpecificData == false) {
+                size_t opusHeadSize = 0;
+                size_t codecDelayBufSize = 0;
+                size_t seekPreRollBufSize = 0;
+                void *opusHeadBuf = NULL;
+                void *codecDelayBuf = NULL;
+                void *seekPreRollBuf = NULL;
+                GetOpusHeaderBuffers((uint8_t*)buffer->data() + buffer->range_offset(),
+                                    buffer->range_length(), &opusHeadBuf,
+                                    &opusHeadSize, &codecDelayBuf,
+                                    &codecDelayBufSize, &seekPreRollBuf,
+                                    &seekPreRollBufSize);
+                writeOggHeaderPackets((unsigned char *)opusHeadBuf, opusHeadSize);
+            } else {
+                ALOGV("ignoring later copy of CSD contained in info buffer");
+            }
             buffer->release();
             buffer = nullptr;
             continue;
         }
 
+        if (mHaveAllCodecSpecificData == false) {
+            ALOGE("Did not get valid opus header before first sample data");
+            buffer->release();
+            buffer = nullptr;
+            err = ERROR_MALFORMED;
+            break;
+        }
+
         int64_t timestampUs;
         CHECK(buffer->meta_data().findInt64(kKeyTime, &timestampUs));
         if (timestampUs > mEstimatedDurationUs) {
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 76a400c..8d0ea3a 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -572,16 +572,17 @@
 }
 
 void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
-    if (portIndex == 0 && mState != NULL) {
-        // Make sure that the next buffer output does not still
-        // depend on fragments from the last one decoded.
-
+    if (portIndex == 0) {
         mInputBufferCount = 0;
         mNumFramesOutput = 0;
         mSawInputEos = false;
         mSignalledOutputEos = false;
         mNumFramesLeftOnPage = -1;
-        vorbis_dsp_restart(mState);
+        if (mState != NULL) {
+            // Make sure that the next buffer output does not still
+            // depend on fragments from the last one decoded.
+            vorbis_dsp_restart(mState);
+        }
     }
 }
 
@@ -603,6 +604,7 @@
     mSawInputEos = false;
     mSignalledOutputEos = false;
     mSignalledError = false;
+    mNumFramesLeftOnPage = -1;
     mOutputPortSettingsChange = NONE;
 }
 
diff --git a/media/libstagefright/include/media/stagefright/OggWriter.h b/media/libstagefright/include/media/stagefright/OggWriter.h
index e3837cd..1a0a1d2 100644
--- a/media/libstagefright/include/media/stagefright/OggWriter.h
+++ b/media/libstagefright/include/media/stagefright/OggWriter.h
@@ -43,6 +43,7 @@
 
 private:
     int mFd;
+    bool mHaveAllCodecSpecificData;
     status_t mInitCheck;
     sp<MediaSource> mSource;
     bool mStarted = false;
@@ -66,6 +67,8 @@
 
     OggWriter(const OggWriter&);
     OggWriter& operator=(const OggWriter&);
+
+    status_t writeOggHeaderPackets(unsigned char *buf, size_t size);
 };
 
 }  // namespace android
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 16fdeaf..b824212 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -128,7 +128,7 @@
     if (isAudioServerOrRootUid(uid)) return true;
     static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
     bool ok = PermissionCache::checkPermission(sCaptureAudioOutput, pid, uid);
-    if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
+    if (!ok) ALOGV("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
     return ok;
 }
 
@@ -149,7 +149,7 @@
         // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
         ok = PermissionCache::checkPermission(sCaptureHotwordAllowed, pid, uid);
     }
-    if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
+    if (!ok) ALOGV("android.permission.CAPTURE_AUDIO_HOTWORD");
     return ok;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index dca84c0..c42923a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -120,8 +120,9 @@
 
     ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
     for (ssize_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == deviceType
-                && itemAt(i)->mDeviceAddress.compare(address) == 0) {
+        // Workaround: when an in audio policy is registered, it opens an output
+        // that tries to find the audio policy, thus the device must be ignored.
+        if (itemAt(i)->mDeviceAddress.compare(address) == 0) {
             policyMix = itemAt(i);
             ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
                     i, deviceType, address.string());
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b0a8541..fa8da89 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -193,7 +193,8 @@
     if (!mPackageManager.allowPlaybackCapture(uid)) {
         attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
     }
-    if (!bypassInterruptionPolicyAllowed(pid, uid)) {
+    if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
+            && !bypassInterruptionPolicyAllowed(pid, uid)) {
         attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
     }
     audio_output_flags_t originalFlags = flags;
@@ -1316,4 +1317,12 @@
     Mutex::Autolock _l(mLock);
     return mAudioPolicyManager->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
 }
+
+status_t AudioPolicyService::setRttEnabled(bool enabled)
+{
+    Mutex::Autolock _l(mLock);
+    mUidPolicy->setRttEnabled(enabled);
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e3c72ae..77f7997 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -409,7 +409,7 @@
 //    following cases:
 //    Another client in the same UID has already been allowed to capture
 //    OR The client is the assistant
-//        AND an accessibility service is on TOP
+//        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
@@ -436,6 +436,9 @@
     bool isAssistantOnTop = false;
     bool isSensitiveActive = false;
     bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
+    bool rttCallActive =
+            (mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
+            && mUidPolicy->isRttEnabled();
 
     // if Sensor Privacy is enabled then all recordings should be silenced.
     if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -518,13 +521,13 @@
             allowCapture = true;
         } else if (mUidPolicy->isAssistantUid(current->uid)) {
             // For assistant allow capture if:
-            //     An accessibility service is on TOP
+            //     An 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
-            if (isA11yOnTop) {
+            if (isA11yOnTop || rttCallActive) {
                 if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
                     allowCapture = true;
                 }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 8db63a5..e467f70 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -256,6 +256,8 @@
     virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
                                                        volume_group_t &volumeGroup);
 
+    virtual status_t setRttEnabled(bool enabled);
+
             status_t doStopOutput(audio_port_handle_t portId);
             void doReleaseOutput(audio_port_handle_t portId);
 
@@ -345,7 +347,8 @@
     class UidPolicy : public BnUidObserver, public virtual IBinder::DeathRecipient {
     public:
         explicit UidPolicy(wp<AudioPolicyService> service)
-                : mService(service), mObserverRegistered(false), mAssistantUid(0) {}
+                : mService(service), mObserverRegistered(false),
+                  mAssistantUid(0), mRttEnabled(false) {}
 
         void registerSelf();
         void unregisterSelf();
@@ -360,6 +363,8 @@
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
         bool isA11yUid(uid_t uid);
         bool isA11yOnTop();
+        void setRttEnabled(bool enabled) { mRttEnabled = enabled; }
+        bool isRttEnabled() { return mRttEnabled; }
 
         // BnUidObserver implementation
         void onUidActive(uid_t uid) override;
@@ -387,6 +392,7 @@
         std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
         uid_t mAssistantUid;
         std::vector<uid_t> mA11yUids;
+        bool mRttEnabled;
     };
 
     // If sensor privacy is enabled then all apps, including those that are active, should be
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 00f0d86..9771f9e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2876,7 +2876,8 @@
     config.streams = streams.editArray();
 
     // Do the HAL configuration; will potentially touch stream
-    // max_buffers, usage, priv fields.
+    // max_buffers, usage, and priv fields, as well as data_space and format
+    // fields for IMPLEMENTATION_DEFINED formats.
 
     const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
     res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
@@ -4202,10 +4203,19 @@
         dst3_2.streamType = streamType;
         dst3_2.width = src->width;
         dst3_2.height = src->height;
-        dst3_2.format = mapToPixelFormat(src->format);
         dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
-        dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
         dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+        // For HidlSession version 3.5 or newer, the format and dataSpace sent
+        // to HAL are original, not the overriden ones.
+        if (mHidlSession_3_5 != nullptr) {
+            dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
+                    cam3stream->getOriginalFormat() : src->format);
+            dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
+                    cam3stream->getOriginalDataSpace() : src->data_space);
+        } else {
+            dst3_2.format = mapToPixelFormat(src->format);
+            dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+        }
         dst3_4.v3_2 = dst3_2;
         dst3_4.bufferSize = bufferSizes[i];
         if (src->physical_camera_id != nullptr) {
@@ -4266,7 +4276,7 @@
                 return OK;
             };
 
-    // See if we have v3.4 or v3.3 HAL
+    // See which version of HAL we have
     if (mHidlSession_3_5 != nullptr) {
         ALOGV("%s: v3.5 device found", __FUNCTION__);
         device::V3_5::StreamConfiguration requestedConfiguration3_5;
@@ -4281,7 +4291,6 @@
     } else if (mHidlSession_3_4 != nullptr) {
         // We do; use v3.4 for the call
         ALOGV("%s: v3.4 device found", __FUNCTION__);
-        device::V3_4::HalStreamConfiguration finalConfiguration3_4;
         auto err = mHidlSession_3_4->configureStreams_3_4(
                 requestedConfiguration3_4, configStream34Cb);
         res = postprocConfigStream34(err);
@@ -4352,12 +4361,12 @@
         device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
 
         Camera3Stream* dstStream = Camera3Stream::cast(dst);
-        dstStream->setFormatOverride(false);
-        dstStream->setDataSpaceOverride(false);
         int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
         android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
 
         if (dst->format != 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);
@@ -4367,10 +4376,13 @@
                         streamId, dst->format);
             }
         } else {
-            dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
-            dstStream->setDataSpaceOverride((dst->data_space != overrideDataSpace) ? true : false);
-
+            bool needFormatOverride =
+                    requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
+            bool needDataspaceOverride =
+                    requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
             // Override allowed with IMPLEMENTATION_DEFINED
+            dstStream->setFormatOverride(needFormatOverride);
+            dstStream->setDataSpaceOverride(needDataspaceOverride);
             dst->format = overrideFormat;
             dst->data_space = overrideDataSpace;
         }
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index e3b74d7..86b45cb 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -55,7 +55,7 @@
 
     mStreamSplitter = new Camera3StreamSplitter(mUseHalBufManager);
 
-    uint64_t usage;
+    uint64_t usage = 0;
     getEndpointUsage(&usage);
 
     std::unordered_map<size_t, sp<Surface>> initialSurfaces;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index d73a2f9..2df084b 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -60,6 +60,8 @@
     mUsage(0),
     mOldUsage(0),
     mOldMaxBuffers(0),
+    mOldFormat(-1),
+    mOldDataSpace(HAL_DATASPACE_UNKNOWN),
     mPrepared(false),
     mPrepareBlockRequest(true),
     mPreparedBufferIdx(0),
@@ -67,6 +69,8 @@
     mBufferLimitLatency(kBufferLimitLatencyBinSize),
     mFormatOverridden(false),
     mOriginalFormat(-1),
+    mDataSpaceOverridden(false),
+    mOriginalDataSpace(HAL_DATASPACE_UNKNOWN),
     mPhysicalCameraId(physicalCameraId),
     mLastTimestamp(0) {
 
@@ -121,7 +125,9 @@
 
 void Camera3Stream::setFormatOverride(bool formatOverridden) {
     mFormatOverridden = formatOverridden;
-    if (formatOverridden) mOriginalFormat = camera3_stream::format;
+    if (formatOverridden && mOriginalFormat == -1) {
+        mOriginalFormat = camera3_stream::format;
+    }
 }
 
 bool Camera3Stream::isFormatOverridden() const {
@@ -134,7 +140,9 @@
 
 void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
     mDataSpaceOverridden = dataSpaceOverridden;
-    if (dataSpaceOverridden) mOriginalDataSpace = camera3_stream::data_space;
+    if (dataSpaceOverridden && mOriginalDataSpace == HAL_DATASPACE_UNKNOWN) {
+        mOriginalDataSpace = camera3_stream::data_space;
+    }
 }
 
 bool Camera3Stream::isDataSpaceOverridden() const {
@@ -250,6 +258,8 @@
 
     mOldUsage = mUsage;
     mOldMaxBuffers = camera3_stream::max_buffers;
+    mOldFormat = camera3_stream::format;
+    mOldDataSpace = camera3_stream::data_space;
 
     res = getEndpointUsage(&mUsage);
     if (res != OK) {
@@ -324,7 +334,9 @@
     // so. As documented in hardware/camera3.h:configure_streams().
     if (mState == STATE_IN_RECONFIG &&
             mOldUsage == mUsage &&
-            mOldMaxBuffers == camera3_stream::max_buffers && !mDataSpaceOverridden) {
+            mOldMaxBuffers == camera3_stream::max_buffers &&
+            mOldDataSpace == camera3_stream::data_space &&
+            mOldFormat == camera3_stream::format) {
         mState = STATE_CONFIGURED;
         return OK;
     }
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index c916fe8..533318f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -540,8 +540,12 @@
     uint64_t mUsage;
 
   private:
+    // Previously configured stream properties (post HAL override)
     uint64_t mOldUsage;
     uint32_t mOldMaxBuffers;
+    int mOldFormat;
+    android_dataspace mOldDataSpace;
+
     Condition mOutputBufferReturnedSignal;
     Condition mInputBufferReturnedSignal;
     static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms