Merge "Querying capability of haptic playback."
diff --git a/camera/Android.bp b/camera/Android.bp
index 24b3918..21588d4 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -43,6 +43,7 @@
         "ICameraRecordingProxyListener.cpp",
         "camera2/CaptureRequest.cpp",
         "camera2/OutputConfiguration.cpp",
+        "camera2/SessionConfiguration.cpp",
         "camera2/SubmitInfo.cpp",
         "CameraBase.cpp",
         "CameraUtils.cpp",
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 4ced08c..49dfde8 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -19,6 +19,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.params.SessionConfiguration;
 import android.hardware.camera2.utils.SubmitInfo;
 import android.view.Surface;
 
@@ -83,6 +84,16 @@
      */
     void endConfigure(int operatingMode, in CameraMetadataNative sessionParams);
 
+    /**
+      * Check whether a particular session configuration has camera device
+      * support.
+      *
+      * @param sessionConfiguration Specific session configuration to be verified.
+      * @return true  - in case the stream combination is supported.
+      *         false - in case there is no device support.
+      */
+    boolean isSessionConfigurationSupported(in SessionConfiguration sessionConfiguration);
+
     void deleteStream(int streamId);
 
     /**
diff --git a/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl b/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl
new file mode 100644
index 0000000..abf1556
--- /dev/null
+++ b/camera/aidl/android/hardware/camera2/params/SessionConfiguration.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+/** @hide */
+parcelable SessionConfiguration cpp_header "camera/camera2/SessionConfiguration.h";
diff --git a/camera/camera2/SessionConfiguration.cpp b/camera/camera2/SessionConfiguration.cpp
new file mode 100644
index 0000000..a431a33
--- /dev/null
+++ b/camera/camera2/SessionConfiguration.cpp
@@ -0,0 +1,133 @@
+/*
+**
+** Copyright 2018, 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 "SessionConfiguration"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include <camera/camera2/SessionConfiguration.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+status_t SessionConfiguration::readFromParcel(const android::Parcel* parcel) {
+    status_t err = OK;
+    int operatingMode = 0;
+
+    if (parcel == nullptr) return BAD_VALUE;
+
+    if ((err = parcel->readInt32(&operatingMode)) != OK) {
+        ALOGE("%s: Failed to read operating mode from parcel", __FUNCTION__);
+        return err;
+    }
+
+    int inputWidth = 0;
+    if ((err = parcel->readInt32(&inputWidth)) != OK) {
+        ALOGE("%s: Failed to read input width from parcel", __FUNCTION__);
+        return err;
+    }
+
+    int inputHeight = 0;
+    if ((err = parcel->readInt32(&inputHeight)) != OK) {
+        ALOGE("%s: Failed to read input height from parcel", __FUNCTION__);
+        return err;
+    }
+
+    int inputFormat = -1;
+    if ((err = parcel->readInt32(&inputFormat)) != OK) {
+        ALOGE("%s: Failed to read input format from parcel", __FUNCTION__);
+        return err;
+    }
+
+    std::vector<OutputConfiguration> outputStreams;
+    if ((err = parcel->readParcelableVector(&outputStreams)) != OK) {
+        ALOGE("%s: Failed to read output configurations from parcel", __FUNCTION__);
+        return err;
+    }
+
+    mOperatingMode = operatingMode;
+    mInputWidth = inputWidth;
+    mInputHeight = inputHeight;
+    mInputFormat = inputFormat;
+    for (auto& stream : outputStreams) {
+        mOutputStreams.push_back(stream);
+    }
+
+
+    return err;
+}
+
+status_t SessionConfiguration::writeToParcel(android::Parcel* parcel) const {
+
+    if (parcel == nullptr) return BAD_VALUE;
+    status_t err = OK;
+
+    err = parcel->writeInt32(mOperatingMode);
+    if (err != OK) return err;
+
+    err = parcel->writeInt32(mInputWidth);
+    if (err != OK) return err;
+
+    err = parcel->writeInt32(mInputHeight);
+    if (err != OK) return err;
+
+    err = parcel->writeInt32(mInputFormat);
+    if (err != OK) return err;
+
+    err = parcel->writeParcelableVector(mOutputStreams);
+    if (err != OK) return err;
+
+    return OK;
+}
+
+bool SessionConfiguration::outputsEqual(const SessionConfiguration& other) const {
+    const std::vector<OutputConfiguration>& otherOutputStreams =
+            other.getOutputConfigurations();
+
+    if (mOutputStreams.size() !=  otherOutputStreams.size()) {
+        return false;
+    }
+
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        if (mOutputStreams[i] != otherOutputStreams[i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool SessionConfiguration::outputsLessThan(const SessionConfiguration& other) const {
+    const std::vector<OutputConfiguration>& otherOutputStreams =
+            other.getOutputConfigurations();
+
+    if (mOutputStreams.size() !=  otherOutputStreams.size()) {
+        return mOutputStreams.size() < otherOutputStreams.size();
+    }
+
+    for (size_t i = 0; i < mOutputStreams.size(); i++) {
+        if (mOutputStreams[i] != otherOutputStreams[i]) {
+            return mOutputStreams[i] < otherOutputStreams[i];
+        }
+    }
+
+    return false;
+}
+
+}; // namespace android
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index ef6930c..b88a2c5 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -29,6 +29,7 @@
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.4",
     ],
     compile_multilib: "32",
     cflags: [
diff --git a/camera/include/camera/camera2/SessionConfiguration.h b/camera/include/camera/camera2/SessionConfiguration.h
new file mode 100644
index 0000000..64288ed
--- /dev/null
+++ b/camera/include/camera/camera2/SessionConfiguration.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 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_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
+#define ANDROID_HARDWARE_CAMERA2_SESSIONCONFIGURATION_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+namespace hardware {
+namespace camera2 {
+namespace params {
+
+class OutputConfiguration;
+
+class SessionConfiguration : public android::Parcelable {
+public:
+
+    const std::vector<OutputConfiguration>& getOutputConfigurations() const {
+        return mOutputStreams;
+    }
+
+    int getInputWidth() const { return mInputWidth; }
+    int getInputHeight() const { return mInputHeight; }
+    int getInputFormat() const { return mInputFormat; }
+    int getOperatingMode() const { return mOperatingMode; }
+
+    virtual status_t writeToParcel(android::Parcel* parcel) const override;
+    virtual status_t readFromParcel(const android::Parcel* parcel) override;
+
+    SessionConfiguration() :
+            mInputWidth(0),
+            mInputHeight(0),
+            mInputFormat(-1),
+            mOperatingMode(-1) {}
+
+    SessionConfiguration(const android::Parcel& parcel) {
+        readFromParcel(&parcel);
+    }
+
+    SessionConfiguration(int inputWidth, int inputHeight, int inputFormat, int operatingMode) :
+        mInputWidth(inputWidth), mInputHeight(inputHeight), mInputFormat(inputFormat),
+        mOperatingMode(operatingMode) {}
+
+    bool operator == (const SessionConfiguration& other) const {
+        return (outputsEqual(other) &&
+                mInputWidth == other.mInputWidth &&
+                mInputHeight == other.mInputHeight &&
+                mInputFormat == other.mInputFormat &&
+                mOperatingMode == other.mOperatingMode);
+    }
+
+    bool operator != (const SessionConfiguration& other) const {
+        return !(*this == other);
+    }
+
+    bool operator < (const SessionConfiguration& other) const {
+        if (*this == other) return false;
+
+        if (mInputWidth != other.mInputWidth) {
+            return mInputWidth < other.mInputWidth;
+        }
+
+        if (mInputHeight != other.mInputHeight) {
+            return mInputHeight < other.mInputHeight;
+        }
+
+        if (mInputFormat != other.mInputFormat) {
+            return mInputFormat < other.mInputFormat;
+        }
+
+        if (mOperatingMode != other.mOperatingMode) {
+            return mOperatingMode < other.mOperatingMode;
+        }
+
+        return outputsLessThan(other);
+    }
+
+    bool operator > (const SessionConfiguration& other) const {
+        return (*this != other && !(*this < other));
+    }
+
+    bool outputsEqual(const SessionConfiguration& other) const;
+    bool outputsLessThan(const SessionConfiguration& other) const;
+    void addOutputConfiguration(const OutputConfiguration &config) {
+        mOutputStreams.push_back(config);
+    }
+
+private:
+
+    std::vector<OutputConfiguration> mOutputStreams;
+    int                              mInputWidth, mInputHeight, mInputFormat, mOperatingMode;
+};
+} // namespace params
+} // namespace camera2
+} // namespace hardware
+
+using hardware::camera2::params::SessionConfiguration;
+
+}; // namespace android
+
+#endif
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index b86f854..26e6b3c 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -754,8 +754,8 @@
         const camera_metadata_t *params_metadata = params.getAndLock();
         utils::convertToHidl(params_metadata, &hidlParams);
         params.unlock(params_metadata);
-        remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE, hidlParams);
     }
+    remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE, hidlParams);
     if (!remoteRet.isOk()) {
         ALOGE("Transaction error: endConfigure failed %s", remoteRet.description().c_str());
     }
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 1de7013..fa8a7a3 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -29,6 +29,7 @@
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
 #include <system/graphics.h>
+#include <hardware/camera3.h>
 #include <hardware/gralloc.h>
 
 #include <camera/CameraMetadata.h>
@@ -40,6 +41,7 @@
 #include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
 #include <camera/camera2/CaptureRequest.h>
 #include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
 
 #include <gui/BufferItemConsumer.h>
@@ -55,6 +57,8 @@
 #include <algorithm>
 
 using namespace android;
+using ::android::hardware::ICameraServiceDefault;
+using ::android::hardware::camera2::ICameraDeviceUser;
 
 #define ASSERT_NOT_NULL(x) \
     ASSERT_TRUE((x) != nullptr)
@@ -490,6 +494,19 @@
         EXPECT_TRUE(res.isOk()) << res;
         EXPECT_FALSE(callbacks->hadError());
 
+        // Session configuration must also be supported in this case
+        SessionConfiguration sessionConfiguration = { /*inputWidth*/ 0, /*inputHeight*/0,
+                /*inputFormat*/ -1, CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE};
+        sessionConfiguration.addOutputConfiguration(output);
+        bool queryStatus;
+        res = device->isSessionConfigurationSupported(sessionConfiguration, &queryStatus);
+        EXPECT_TRUE(res.isOk() ||
+                (res.serviceSpecificErrorCode() == ICameraServiceDefault::ERROR_INVALID_OPERATION))
+                << res;
+        if (res.isOk()) {
+            EXPECT_TRUE(queryStatus);
+        }
+
         // Can we make requests?
         CameraMetadata requestTemplate;
         res = device->createDefaultRequest(/*preview template*/1,
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index 38962e5..b480bbe 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -69,6 +69,40 @@
     bool     (*supportsNonBlockingRead)(void *data);
 };
 
+/**
+ * only use CMediaBufferV3 allocated from the CMediaBufferGroupV3 that is
+ * provided to CMediaTrack::start()
+ */
+struct CMediaBufferV3 {
+    void *handle;
+    void (*release)(void *handle);
+    void* (*data)(void *handle);
+    size_t (*size)(void *handle);
+    size_t (*range_offset)(void *handle);
+    size_t (*range_length)(void *handle);
+    void (*set_range)(void *handle, size_t offset, size_t length);
+    AMediaFormat* (*meta_data)(void *handle);
+};
+
+struct CMediaBufferGroupV3 {
+    void *handle;
+    bool (*init)(void *handle, size_t buffers, size_t buffer_size, size_t growthLimit);
+    void (*add_buffer)(void *handle, size_t size);
+    media_status_t (*acquire_buffer)(void *handle,
+            CMediaBufferV3 **buffer, bool nonBlocking, size_t requestedSize);
+    bool (*has_buffers)(void *handle);
+};
+
+struct CMediaTrackV3 {
+    void *data;
+    void (*free)(void *data);
+
+    media_status_t (*start)(void *data, CMediaBufferGroupV3 *bufferGroup);
+    media_status_t (*stop)(void *data);
+    media_status_t (*getFormat)(void *data, AMediaFormat *format);
+    media_status_t (*read)(void *data, CMediaBufferV3 **buffer, uint32_t options, int64_t seekPosUs);
+    bool     (*supportsNonBlockingRead)(void *data);
+};
 
 struct CMediaExtractorV1 {
     void *data;
@@ -104,6 +138,23 @@
     const char * (*name)(void *data);
 };
 
+struct CMediaExtractorV3 {
+    void *data;
+
+    void (*free)(void *data);
+    size_t (*countTracks)(void *data);
+    CMediaTrackV3* (*getTrack)(void *data, size_t index);
+    media_status_t (*getTrackMetaData)(
+            void *data,
+            AMediaFormat *meta,
+            size_t index, uint32_t flags);
+
+    media_status_t (*getMetaData)(void *data, AMediaFormat *meta);
+    uint32_t (*flags)(void *data);
+    media_status_t (*setMediaCas)(void *data, const uint8_t* casToken, size_t size);
+    const char * (*name)(void *data);
+};
+
 typedef CMediaExtractorV1* (*CreatorFuncV1)(CDataSource *source, void *meta);
 typedef void (*FreeMetaFunc)(void *meta);
 
@@ -121,6 +172,12 @@
         CDataSource *source, float *confidence,
         void **meta, FreeMetaFunc *freeMeta);
 
+typedef CMediaExtractorV3* (*CreatorFuncV3)(CDataSource *source, void *meta);
+
+typedef CreatorFuncV3 (*SnifferFuncV3)(
+        CDataSource *source, float *confidence,
+        void **meta, FreeMetaFunc *freeMeta);
+
 typedef CMediaExtractorV1 CMediaExtractor;
 typedef CreatorFuncV1 CreatorFunc;
 
@@ -148,6 +205,7 @@
     union {
         SnifferFuncV1 v1;
         SnifferFuncV2 v2;
+        SnifferFuncV3 v3;
     } sniff;
 };
 
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
index 858c575..292ec93 100644
--- a/include/media/MediaExtractorPluginHelper.h
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -20,12 +20,13 @@
 
 #include <arpa/inet.h>
 #include <stdio.h>
-#include <vector>
+#include <map>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
 #include <media/MediaExtractorPluginApi.h>
+#include <media/NdkMediaFormat.h>
 
 namespace android {
 
@@ -171,6 +172,176 @@
     return wrapper;
 }
 
+class MediaTrackHelperV3;
+
+class MediaBufferHelperV3 {
+private:
+    friend CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *);
+    CMediaBufferV3 *mBuffer;
+public:
+    MediaBufferHelperV3(CMediaBufferV3 *buf) {
+        mBuffer = buf;
+    }
+
+    ~MediaBufferHelperV3() {}
+
+    void release() {
+        mBuffer->release(mBuffer->handle);
+    }
+
+    void* data() {
+        return mBuffer->data(mBuffer->handle);
+    }
+
+    size_t size() {
+        return mBuffer->size(mBuffer->handle);
+    }
+
+    size_t range_offset() {
+        return mBuffer->range_offset(mBuffer->handle);
+    }
+
+    size_t range_length() {
+        return mBuffer->range_length(mBuffer->handle);
+    }
+
+    void set_range(size_t offset, size_t length) {
+        mBuffer->set_range(mBuffer->handle, offset, length);
+    }
+    AMediaFormat *meta_data() {
+        return mBuffer->meta_data(mBuffer->handle);
+    }
+};
+
+class MediaBufferGroupHelperV3 {
+private:
+    CMediaBufferGroupV3 *mGroup;
+    std::map<CMediaBufferV3*, MediaBufferHelperV3*> mBufferHelpers;
+public:
+    MediaBufferGroupHelperV3(CMediaBufferGroupV3 *group) {
+        mGroup = group;
+    }
+    ~MediaBufferGroupHelperV3() {
+        // delete all entries in map
+        ALOGV("buffergroup %p map has %zu entries", this, mBufferHelpers.size());
+        for (auto it = mBufferHelpers.begin(); it != mBufferHelpers.end(); ++it) {
+            delete it->second;
+        }
+    }
+    bool init(size_t buffers, size_t buffer_size, size_t growthLimit = 0) {
+        return mGroup->init(mGroup->handle, buffers, buffer_size, growthLimit);
+    }
+    void add_buffer(size_t size) {
+        mGroup->add_buffer(mGroup->handle, size);
+    }
+    media_status_t acquire_buffer(
+            MediaBufferHelperV3 **buffer, bool nonBlocking = false, size_t requestedSize = 0) {
+        CMediaBufferV3 *buf = nullptr;
+        media_status_t ret =
+                mGroup->acquire_buffer(mGroup->handle, &buf, nonBlocking, requestedSize);
+        if (ret == AMEDIA_OK && buf != nullptr) {
+            auto helper = mBufferHelpers.find(buf);
+            if (helper == mBufferHelpers.end()) {
+                MediaBufferHelperV3* newHelper = new MediaBufferHelperV3(buf);
+                mBufferHelpers.insert(std::make_pair(buf, newHelper));
+                *buffer = newHelper;
+            } else {
+                *buffer = helper->second;
+            }
+        } else {
+            *buffer = nullptr;
+        }
+        return ret;
+    }
+    bool has_buffers() {
+        return mGroup->has_buffers(mGroup->handle);
+    }
+};
+
+class MediaTrackHelperV3 {
+public:
+    MediaTrackHelperV3() : mBufferGroup(nullptr) {
+    }
+    virtual ~MediaTrackHelperV3() {
+        delete mBufferGroup;
+    }
+    virtual media_status_t start() = 0;
+    virtual media_status_t stop() = 0;
+    virtual media_status_t getFormat(AMediaFormat *format) = 0;
+
+    class ReadOptions {
+    public:
+        enum SeekMode : int32_t {
+            SEEK_PREVIOUS_SYNC,
+            SEEK_NEXT_SYNC,
+            SEEK_CLOSEST_SYNC,
+            SEEK_CLOSEST,
+            SEEK_FRAME_INDEX,
+        };
+
+        ReadOptions(uint32_t options, int64_t seekPosUs) {
+            mOptions = options;
+            mSeekPosUs = seekPosUs;
+        }
+        bool getSeekTo(int64_t *time_us, SeekMode *mode) const {
+            if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) {
+                return false;
+            }
+            *time_us = mSeekPosUs;
+            *mode = (SeekMode) (mOptions & 7);
+            return true;
+        }
+        bool getNonBlocking() const {
+            return mOptions & CMediaTrackReadOptions::NONBLOCKING;
+        }
+    private:
+        uint32_t mOptions;
+        int64_t mSeekPosUs;
+    };
+
+    virtual media_status_t read(
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL) = 0;
+    virtual bool supportsNonBlockingRead() { return false; }
+protected:
+    friend CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *track);
+    MediaBufferGroupHelperV3 *mBufferGroup;
+};
+
+inline CMediaTrackV3 *wrapV3(MediaTrackHelperV3 *track) {
+    CMediaTrackV3 *wrapper = (CMediaTrackV3*) malloc(sizeof(CMediaTrackV3));
+    wrapper->data = track;
+    wrapper->free = [](void *data) -> void {
+        delete (MediaTrackHelperV3*)(data);
+    };
+    wrapper->start = [](void *data, CMediaBufferGroupV3 *bufferGroup) -> media_status_t {
+        if (((MediaTrackHelperV3*)data)->mBufferGroup) {
+            // this shouldn't happen, but handle it anyway
+            delete ((MediaTrackHelperV3*)data)->mBufferGroup;
+        }
+        ((MediaTrackHelperV3*)data)->mBufferGroup = new MediaBufferGroupHelperV3(bufferGroup);
+        return ((MediaTrackHelperV3*)data)->start();
+    };
+    wrapper->stop = [](void *data) -> media_status_t {
+        return ((MediaTrackHelperV3*)data)->stop();
+    };
+    wrapper->getFormat = [](void *data, AMediaFormat *meta) -> media_status_t {
+        return ((MediaTrackHelperV3*)data)->getFormat(meta);
+    };
+    wrapper->read = [](void *data, CMediaBufferV3 **buffer,  uint32_t options, int64_t seekPosUs)
+            -> media_status_t {
+        MediaTrackHelperV3::ReadOptions opts(options, seekPosUs);
+        MediaBufferHelperV3 *buf = NULL;
+        media_status_t ret = ((MediaTrackHelperV3*)data)->read(&buf, &opts);
+        if (ret == AMEDIA_OK && buf != nullptr) {
+            *buffer = buf->mBuffer;
+        }
+        return ret;
+    };
+    wrapper->supportsNonBlockingRead = [](void *data) -> bool {
+                return ((MediaTrackHelperV3*)data)->supportsNonBlockingRead();
+    };
+    return wrapper;
+}
 
 
 // extractor plugins can derive from this class which looks remarkably
@@ -341,6 +512,89 @@
     return wrapper;
 }
 
+class MediaExtractorPluginHelperV3
+{
+public:
+    virtual ~MediaExtractorPluginHelperV3() {}
+    virtual size_t countTracks() = 0;
+    virtual MediaTrackHelperV3 *getTrack(size_t index) = 0;
+
+    enum GetTrackMetaDataFlags {
+        kIncludeExtensiveMetaData = 1
+    };
+    virtual media_status_t getTrackMetaData(
+            AMediaFormat *meta,
+            size_t index, uint32_t flags = 0) = 0;
+
+    // Return container specific meta-data. The default implementation
+    // returns an empty metadata object.
+    virtual media_status_t getMetaData(AMediaFormat *meta) = 0;
+
+    enum Flags {
+        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
+        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
+        CAN_PAUSE          = 4,
+        CAN_SEEK           = 8,  // the "seek bar"
+    };
+
+    // If subclasses do _not_ override this, the default is
+    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
+    virtual uint32_t flags() const {
+        return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
+    };
+
+    virtual media_status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
+        return AMEDIA_ERROR_INVALID_OPERATION;
+    }
+
+    virtual const char * name() { return "<unspecified>"; }
+
+protected:
+    MediaExtractorPluginHelperV3() {}
+
+private:
+    MediaExtractorPluginHelperV3(const MediaExtractorPluginHelperV2 &);
+    MediaExtractorPluginHelperV3 &operator=(const MediaExtractorPluginHelperV2 &);
+};
+
+inline CMediaExtractorV3 *wrapV3(MediaExtractorPluginHelperV3 *extractor) {
+    CMediaExtractorV3 *wrapper = (CMediaExtractorV3*) malloc(sizeof(CMediaExtractorV3));
+    wrapper->data = extractor;
+    wrapper->free = [](void *data) -> void {
+        delete (MediaExtractorPluginHelperV3*)(data);
+    };
+    wrapper->countTracks = [](void *data) -> size_t {
+        return ((MediaExtractorPluginHelperV3*)data)->countTracks();
+    };
+    wrapper->getTrack = [](void *data, size_t index) -> CMediaTrackV3* {
+        return wrapV3(((MediaExtractorPluginHelperV3*)data)->getTrack(index));
+    };
+    wrapper->getTrackMetaData = [](
+            void *data,
+            AMediaFormat *meta,
+            size_t index, uint32_t flags) -> media_status_t {
+        return ((MediaExtractorPluginHelperV3*)data)->getTrackMetaData(meta, index, flags);
+    };
+    wrapper->getMetaData = [](
+            void *data,
+            AMediaFormat *meta) -> media_status_t {
+        return ((MediaExtractorPluginHelperV3*)data)->getMetaData(meta);
+    };
+    wrapper->flags = [](
+            void *data) -> uint32_t {
+        return ((MediaExtractorPluginHelperV3*)data)->flags();
+    };
+    wrapper->setMediaCas = [](
+            void *data, const uint8_t *casToken, size_t size) -> media_status_t {
+        return ((MediaExtractorPluginHelperV3*)data)->setMediaCas(casToken, size);
+    };
+    wrapper->name = [](
+            void *data) -> const char * {
+        return ((MediaExtractorPluginHelperV3*)data)->name();
+    };
+    return wrapper;
+}
+
 /* adds some convience methods */
 class DataSourceHelper {
 public:
diff --git a/include/media/MediaTrack.h b/include/media/MediaTrack.h
index ee3591e..baa3410 100644
--- a/include/media/MediaTrack.h
+++ b/include/media/MediaTrack.h
@@ -23,6 +23,7 @@
 #include <binder/IMemory.h>
 #include <binder/MemoryDealer.h>
 #include <media/MediaExtractorPluginApi.h>
+#include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/MediaExtractorPluginApi.h>
@@ -175,6 +176,25 @@
     CMediaTrackV2 *wrapper;
 };
 
+class MediaTrackCUnwrapperV3 : public MediaTrack {
+public:
+    explicit MediaTrackCUnwrapperV3(CMediaTrackV3 *wrapper);
+
+    virtual status_t start();
+    virtual status_t stop();
+    virtual status_t getFormat(MetaDataBase& format);
+    virtual status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
+
+    virtual bool supportNonblockingRead();
+
+protected:
+    virtual ~MediaTrackCUnwrapperV3();
+
+private:
+    CMediaTrackV3 *wrapper;
+    MediaBufferGroup *bufferGroup;
+};
+
 }  // namespace android
 
 #endif  // MEDIA_SOURCE_BASE_H_
diff --git a/include/media/NdkMediaErrorPriv.h b/include/media/NdkMediaErrorPriv.h
index f5e2f02..3bbba79 100644
--- a/include/media/NdkMediaErrorPriv.h
+++ b/include/media/NdkMediaErrorPriv.h
@@ -20,10 +20,8 @@
 #include <media/NdkMediaError.h>
 #include <utils/Errors.h>
 
-using namespace android;
+media_status_t translate_error(android::status_t);
 
-media_status_t translate_error(status_t);
-
-status_t reverse_translate_error(media_status_t);
+android::status_t reverse_translate_error(media_status_t);
 
 #endif // _NDK_MEDIA_ERROR_PRIV_H
diff --git a/include/media/NdkMediaFormatPriv.h b/include/media/NdkMediaFormatPriv.h
index 6c452c3..1fda4a8 100644
--- a/include/media/NdkMediaFormatPriv.h
+++ b/include/media/NdkMediaFormatPriv.h
@@ -27,6 +27,7 @@
 #ifndef _NDK_MEDIA_FORMAT_PRIV_H
 #define _NDK_MEDIA_FORMAT_PRIV_H
 
+#include <utils/KeyedVector.h>
 #include <utils/String8.h>
 #include <utils/StrongPointer.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -35,20 +36,22 @@
 extern "C" {
 #endif
 
-using namespace android;
-
 struct AMediaFormat {
-    sp<AMessage> mFormat;
-    String8 mDebug;
-    KeyedVector<String8, String8> mStringCache;
+    android::sp<android::AMessage> mFormat;
+    android::String8 mDebug;
+    android::KeyedVector<android::String8, android::String8> mStringCache;
 };
 
-AMediaFormat* AMediaFormat_fromMsg(const void*);
-void AMediaFormat_getFormat(const AMediaFormat* mData, void* dest);
-
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
+namespace android {
+
+AMediaFormat* AMediaFormat_fromMsg(sp<AMessage> *);
+void AMediaFormat_getFormat(const AMediaFormat* mData, sp<AMessage> *dest);
+
+} // namespace android
+
 #endif // _NDK_MEDIA_FORMAT_PRIV_H
 
diff --git a/media/codec2/components/base/Android.bp b/media/codec2/components/base/Android.bp
index 06bb81a..d02f541 100644
--- a/media/codec2/components/base/Android.bp
+++ b/media/codec2/components/base/Android.bp
@@ -31,9 +31,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index 994dfee..6b0977b 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -33,8 +33,5 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 799ade4..27aa064 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -194,6 +194,7 @@
     kParamIndexLayerIndex,
     kParamIndexLayerCount,
     kParamIndexIntraRefresh,
+    kParamIndexHdr10PlusMetadata,
 
     /* ------------------------------------ image components ------------------------------------ */
 
@@ -1560,6 +1561,14 @@
         C2StreamHdrStaticInfo;
 constexpr char C2_PARAMKEY_HDR_STATIC_INFO[] = "raw.hdr-static-info";
 
+/**
+ * HDR10+ Metadata Info.
+ */
+typedef C2StreamParam<C2Info, C2BlobValue, kParamIndexHdr10PlusMetadata>
+        C2StreamHdr10PlusInfo;
+constexpr char C2_PARAMKEY_INPUT_HDR10_PLUS_INFO[] = "input.hdr10-plus-info";
+constexpr char C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO[] = "output.hdr10-plus-info";
+
 /* ------------------------------------ block-based coding ----------------------------------- */
 
 /**
diff --git a/media/codec2/faultinjection/Android.bp b/media/codec2/faultinjection/Android.bp
index ade638f..a0ad3ce 100644
--- a/media/codec2/faultinjection/Android.bp
+++ b/media/codec2/faultinjection/Android.bp
@@ -22,9 +22,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index ddeb4ff..26bd96c 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -76,7 +76,11 @@
 
 // Convenience methods to obtain known clients.
 std::shared_ptr<Codec2Client> getClient(size_t index) {
-    return Codec2Client::CreateFromService(kClientNames[index]);
+    uint32_t serviceMask = ::android::base::GetUintProperty(
+            "debug.media.codec2", uint32_t(0));
+    return Codec2Client::CreateFromService(
+            kClientNames[index],
+            (serviceMask & (1 << index)) != 0);
 }
 
 ClientList getClientList() {
@@ -633,9 +637,13 @@
             Base::tryGetService(instanceName);
     if (!baseStore) {
         if (waitForService) {
-            ALOGE("Codec2.0 service inaccessible. Check the device manifest.");
+            ALOGW("Codec2.0 service \"%s\" inaccessible. "
+                  "Check the device manifest.",
+                  instanceName);
         } else {
-            ALOGW("Codec2.0 service not available right now. Try again later.");
+            ALOGD("Codec2.0 service \"%s\" unavailable right now. "
+                  "Try again later.",
+                  instanceName);
         }
         return nullptr;
     }
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 965971e..216525e 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -37,58 +37,3 @@
     compile_multilib: "32",
 }
 
-cc_library_shared {
-    name: "libcodec2_serviceregistrant",
-    // need vendor version for update packaging, system version may have more dependencies
-    vendor_available: true,
-    srcs: [
-        "C2SoftwareCodecServiceRegistrant.cpp",
-    ],
-
-    header_libs: [
-        "libmedia_headers",
-    ],
-
-    shared_libs: [
-        "android.hardware.media.c2@1.0",
-        "libcodec2_hidl@1.0",
-        "libcodec2_vndk",
-        "liblog",
-        "libutils",
-    ],
-
-    // Codecs
-    runtime_libs: [
-        "libcodec2_soft_avcdec",
-        "libcodec2_soft_avcenc",
-        "libcodec2_soft_aacdec",
-        "libcodec2_soft_aacenc",
-        "libcodec2_soft_amrnbdec",
-        "libcodec2_soft_amrnbenc",
-        "libcodec2_soft_amrwbdec",
-        "libcodec2_soft_amrwbenc",
-        "libcodec2_soft_hevcdec",
-        "libcodec2_soft_g711alawdec",
-        "libcodec2_soft_g711mlawdec",
-        "libcodec2_soft_mpeg2dec",
-        "libcodec2_soft_h263dec",
-        "libcodec2_soft_h263enc",
-        "libcodec2_soft_mpeg4dec",
-        "libcodec2_soft_mpeg4enc",
-        "libcodec2_soft_mp3dec",
-        "libcodec2_soft_vorbisdec",
-        "libcodec2_soft_opusdec",
-        "libcodec2_soft_vp8dec",
-        "libcodec2_soft_vp9dec",
-        "libcodec2_soft_vp8enc",
-        "libcodec2_soft_vp9enc",
-        "libcodec2_soft_rawdec",
-        "libcodec2_soft_flacdec",
-        "libcodec2_soft_flacenc",
-        "libcodec2_soft_gsmdec",
-        "libcodec2_soft_xaacdec",
-    ],
-
-    compile_multilib: "32",
-}
-
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index f5578726..2870d39 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -54,8 +54,5 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index bd4983c..eb6c3e9 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -32,8 +32,5 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
index 7a460f4..4c330e5 100644
--- a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
+++ b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
@@ -26,6 +26,12 @@
 /* static */ android::Mutex C2PlatformStorePluginLoader::sMutex;
 /* static */ std::unique_ptr<C2PlatformStorePluginLoader> C2PlatformStorePluginLoader::sInstance;
 
+namespace /* unnamed */ {
+
+constexpr const char kStorePluginPath[] = "libc2plugin_store.so";
+
+}  // unnamed
+
 C2PlatformStorePluginLoader::C2PlatformStorePluginLoader(const char *libPath)
     : mCreateBlockPool(nullptr) {
     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
@@ -89,7 +95,7 @@
     android::Mutex::Autolock _l(sMutex);
     if (!sInstance) {
         ALOGV("Loading library");
-        sInstance.reset(new C2PlatformStorePluginLoader("libstagefright_ccodec_ext.so"));
+        sInstance.reset(new C2PlatformStorePluginLoader(kStorePluginPath));
     }
     return sInstance;
 }
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 33019ed..2d4e19e 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -798,65 +798,65 @@
         mComponentsList.emplace_back(alias);
     };
     // TODO: move this also into a .so so it can be updated
-    emplace("c2.android.avc.decoder", "libstagefright_soft_c2avcdec.so");
-    emplace("c2.android.avc.encoder", "libstagefright_soft_c2avcenc.so");
-    emplace("c2.android.aac.decoder", "libstagefright_soft_c2aacdec.so");
-    emplace("c2.android.aac.encoder", "libstagefright_soft_c2aacenc.so");
-    emplace("c2.android.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so");
-    emplace("c2.android.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so");
-    emplace("c2.android.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so");
-    emplace("c2.android.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so");
-    emplace("c2.android.hevc.decoder", "libstagefright_soft_c2hevcdec.so");
-    emplace("c2.android.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so");
-    emplace("c2.android.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so");
-    emplace("c2.android.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so");
-    emplace("c2.android.h263.decoder", "libstagefright_soft_c2h263dec.so");
-    emplace("c2.android.h263.encoder", "libstagefright_soft_c2h263enc.so");
-    emplace("c2.android.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so");
-    emplace("c2.android.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so");
-    emplace("c2.android.mp3.decoder", "libstagefright_soft_c2mp3dec.so");
-    emplace("c2.android.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so");
-    emplace("c2.android.opus.decoder", "libstagefright_soft_c2opusdec.so");
-    emplace("c2.android.vp8.decoder", "libstagefright_soft_c2vp8dec.so");
-    emplace("c2.android.vp9.decoder", "libstagefright_soft_c2vp9dec.so");
-    emplace("c2.android.vp8.encoder", "libstagefright_soft_c2vp8enc.so");
-    emplace("c2.android.vp9.encoder", "libstagefright_soft_c2vp9enc.so");
-    emplace("c2.android.raw.decoder", "libstagefright_soft_c2rawdec.so");
-    emplace("c2.android.flac.decoder", "libstagefright_soft_c2flacdec.so");
-    emplace("c2.android.flac.encoder", "libstagefright_soft_c2flacenc.so");
-    emplace("c2.android.gsm.decoder", "libstagefright_soft_c2gsmdec.so");
-    emplace("c2.android.xaac.decoder", "libstagefright_soft_c2xaacdec.so");
+    emplace("c2.android.avc.decoder", "libcodec2_soft_avcdec.so");
+    emplace("c2.android.avc.encoder", "libcodec2_soft_avcenc.so");
+    emplace("c2.android.aac.decoder", "libcodec2_soft_aacdec.so");
+    emplace("c2.android.aac.encoder", "libcodec2_soft_aacenc.so");
+    emplace("c2.android.amrnb.decoder", "libcodec2_soft_amrnbdec.so");
+    emplace("c2.android.amrnb.encoder", "libcodec2_soft_amrnbenc.so");
+    emplace("c2.android.amrwb.decoder", "libcodec2_soft_amrwbdec.so");
+    emplace("c2.android.amrwb.encoder", "libcodec2_soft_amrwbenc.so");
+    emplace("c2.android.hevc.decoder", "libcodec2_soft_hevcdec.so");
+    emplace("c2.android.g711.alaw.decoder", "libcodec2_soft_g711alawdec.so");
+    emplace("c2.android.g711.mlaw.decoder", "libcodec2_soft_g711mlawdec.so");
+    emplace("c2.android.mpeg2.decoder", "libcodec2_soft_mpeg2dec.so");
+    emplace("c2.android.h263.decoder", "libcodec2_soft_h263dec.so");
+    emplace("c2.android.h263.encoder", "libcodec2_soft_h263enc.so");
+    emplace("c2.android.mpeg4.decoder", "libcodec2_soft_mpeg4dec.so");
+    emplace("c2.android.mpeg4.encoder", "libcodec2_soft_mpeg4enc.so");
+    emplace("c2.android.mp3.decoder", "libcodec2_soft_mp3dec.so");
+    emplace("c2.android.vorbis.decoder", "libcodec2_soft_vorbisdec.so");
+    emplace("c2.android.opus.decoder", "libcodec2_soft_opusdec.so");
+    emplace("c2.android.vp8.decoder", "libcodec2_soft_vp8dec.so");
+    emplace("c2.android.vp9.decoder", "libcodec2_soft_vp9dec.so");
+    emplace("c2.android.vp8.encoder", "libcodec2_soft_vp8enc.so");
+    emplace("c2.android.vp9.encoder", "libcodec2_soft_vp9enc.so");
+    emplace("c2.android.raw.decoder", "libcodec2_soft_rawdec.so");
+    emplace("c2.android.flac.decoder", "libcodec2_soft_flacdec.so");
+    emplace("c2.android.flac.encoder", "libcodec2_soft_flacenc.so");
+    emplace("c2.android.gsm.decoder", "libcodec2_soft_gsmdec.so");
+    emplace("c2.android.xaac.decoder", "libcodec2_soft_xaacdec.so");
 
     // "Aliases"
     // TODO: use aliases proper from C2Component::Traits
-    emplace("OMX.google.h264.decoder", "libstagefright_soft_c2avcdec.so");
-    emplace("OMX.google.h264.encoder", "libstagefright_soft_c2avcenc.so");
-    emplace("OMX.google.aac.decoder", "libstagefright_soft_c2aacdec.so");
-    emplace("OMX.google.aac.encoder", "libstagefright_soft_c2aacenc.so");
-    emplace("OMX.google.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so");
-    emplace("OMX.google.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so");
-    emplace("OMX.google.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so");
-    emplace("OMX.google.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so");
-    emplace("OMX.google.hevc.decoder", "libstagefright_soft_c2hevcdec.so");
-    emplace("OMX.google.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so");
-    emplace("OMX.google.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so");
-    emplace("OMX.google.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so");
-    emplace("OMX.google.h263.decoder", "libstagefright_soft_c2h263dec.so");
-    emplace("OMX.google.h263.encoder", "libstagefright_soft_c2h263enc.so");
-    emplace("OMX.google.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so");
-    emplace("OMX.google.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so");
-    emplace("OMX.google.mp3.decoder", "libstagefright_soft_c2mp3dec.so");
-    emplace("OMX.google.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so");
-    emplace("OMX.google.opus.decoder", "libstagefright_soft_c2opusdec.so");
-    emplace("OMX.google.vp8.decoder", "libstagefright_soft_c2vp8dec.so");
-    emplace("OMX.google.vp9.decoder", "libstagefright_soft_c2vp9dec.so");
-    emplace("OMX.google.vp8.encoder", "libstagefright_soft_c2vp8enc.so");
-    emplace("OMX.google.vp9.encoder", "libstagefright_soft_c2vp9enc.so");
-    emplace("OMX.google.raw.decoder", "libstagefright_soft_c2rawdec.so");
-    emplace("OMX.google.flac.decoder", "libstagefright_soft_c2flacdec.so");
-    emplace("OMX.google.flac.encoder", "libstagefright_soft_c2flacenc.so");
-    emplace("OMX.google.gsm.decoder", "libstagefright_soft_c2gsmdec.so");
-    emplace("OMX.google.xaac.decoder", "libstagefright_soft_c2xaacdec.so");
+    emplace("OMX.google.h264.decoder", "libcodec2_soft_avcdec.so");
+    emplace("OMX.google.h264.encoder", "libcodec2_soft_avcenc.so");
+    emplace("OMX.google.aac.decoder", "libcodec2_soft_aacdec.so");
+    emplace("OMX.google.aac.encoder", "libcodec2_soft_aacenc.so");
+    emplace("OMX.google.amrnb.decoder", "libcodec2_soft_amrnbdec.so");
+    emplace("OMX.google.amrnb.encoder", "libcodec2_soft_amrnbenc.so");
+    emplace("OMX.google.amrwb.decoder", "libcodec2_soft_amrwbdec.so");
+    emplace("OMX.google.amrwb.encoder", "libcodec2_soft_amrwbenc.so");
+    emplace("OMX.google.hevc.decoder", "libcodec2_soft_hevcdec.so");
+    emplace("OMX.google.g711.alaw.decoder", "libcodec2_soft_g711alawdec.so");
+    emplace("OMX.google.g711.mlaw.decoder", "libcodec2_soft_g711mlawdec.so");
+    emplace("OMX.google.mpeg2.decoder", "libcodec2_soft_mpeg2dec.so");
+    emplace("OMX.google.h263.decoder", "libcodec2_soft_h263dec.so");
+    emplace("OMX.google.h263.encoder", "libcodec2_soft_h263enc.so");
+    emplace("OMX.google.mpeg4.decoder", "libcodec2_soft_mpeg4dec.so");
+    emplace("OMX.google.mpeg4.encoder", "libcodec2_soft_mpeg4enc.so");
+    emplace("OMX.google.mp3.decoder", "libcodec2_soft_mp3dec.so");
+    emplace("OMX.google.vorbis.decoder", "libcodec2_soft_vorbisdec.so");
+    emplace("OMX.google.opus.decoder", "libcodec2_soft_opusdec.so");
+    emplace("OMX.google.vp8.decoder", "libcodec2_soft_vp8dec.so");
+    emplace("OMX.google.vp9.decoder", "libcodec2_soft_vp9dec.so");
+    emplace("OMX.google.vp8.encoder", "libcodec2_soft_vp8enc.so");
+    emplace("OMX.google.vp9.encoder", "libcodec2_soft_vp9enc.so");
+    emplace("OMX.google.raw.decoder", "libcodec2_soft_rawdec.so");
+    emplace("OMX.google.flac.decoder", "libcodec2_soft_flacdec.so");
+    emplace("OMX.google.flac.encoder", "libcodec2_soft_flacenc.so");
+    emplace("OMX.google.gsm.decoder", "libcodec2_soft_gsmdec.so");
+    emplace("OMX.google.xaac.decoder", "libcodec2_soft_xaacdec.so");
 }
 
 c2_status_t C2PlatformComponentStore::copyBuffer(
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index f278107..9384ebf 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -31,7 +31,7 @@
 
 namespace android {
 
-class AACSource : public MediaTrackHelperV2 {
+class AACSource : public MediaTrackHelperV3 {
 public:
     AACSource(
             DataSourceHelper *source,
@@ -45,7 +45,7 @@
     virtual media_status_t getFormat(AMediaFormat*);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~AACSource();
@@ -58,7 +58,6 @@
     off64_t mOffset;
     int64_t mCurrentTimeUs;
     bool mStarted;
-    MediaBufferGroup *mGroup;
 
     Vector<uint64_t> mOffsetVector;
     int64_t mFrameDurationUs;
@@ -196,7 +195,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *AACExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *AACExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -227,7 +226,6 @@
       mOffset(0),
       mCurrentTimeUs(0),
       mStarted(false),
-      mGroup(NULL),
       mOffsetVector(offset_vector),
       mFrameDurationUs(frame_duration_us) {
 }
@@ -248,8 +246,7 @@
     }
 
     mCurrentTimeUs = 0;
-    mGroup = new MediaBufferGroup;
-    mGroup->add_buffer(MediaBufferBase::Create(kMaxFrameSize));
+    mBufferGroup->add_buffer(kMaxFrameSize);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -258,9 +255,6 @@
 media_status_t AACSource::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
     return AMEDIA_OK;
 }
@@ -270,7 +264,7 @@
 }
 
 media_status_t AACSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -293,8 +287,8 @@
         return AMEDIA_ERROR_END_OF_STREAM;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -309,8 +303,9 @@
     }
 
     buffer->set_range(0, frameSizeWithoutHeader);
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += mFrameDurationUs;
@@ -321,14 +316,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *meta) {
     off64_t offset = *static_cast<off64_t*>(meta);
-    return wrapV2(new AACExtractor(new DataSourceHelper(source), offset));
+    return wrapV3(new AACExtractor(new DataSourceHelper(source), offset));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source, float *confidence, void **meta,
         FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
@@ -388,11 +383,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
         1, // version
         "AAC Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index 3b11f95..be33bf5 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -29,12 +29,12 @@
 struct AMessage;
 class String8;
 
-class AACExtractor : public MediaExtractorPluginHelperV2 {
+class AACExtractor : public MediaExtractorPluginHelperV3 {
 public:
     AACExtractor(DataSourceHelper *source, off64_t offset);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 42b0a64..a58167a 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
@@ -36,9 +35,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 511b14d..7fd2a41 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -29,7 +29,7 @@
 
 namespace android {
 
-class AMRSource : public MediaTrackHelperV2 {
+class AMRSource : public MediaTrackHelperV3 {
 public:
     AMRSource(
             DataSourceHelper *source,
@@ -44,7 +44,7 @@
     virtual media_status_t getFormat(AMediaFormat *);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~AMRSource();
@@ -209,7 +209,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *AMRExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *AMRExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -255,8 +255,7 @@
 
     mOffset = mIsWide ? 9 : 6;
     mCurrentTimeUs = 0;
-    mGroup = new MediaBufferGroup;
-    mGroup->add_buffer(MediaBufferBase::Create(128));
+    mBufferGroup->add_buffer(128);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -265,9 +264,6 @@
 media_status_t AMRSource::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
     return AMEDIA_OK;
 }
@@ -277,7 +273,7 @@
 }
 
 media_status_t AMRSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -326,8 +322,8 @@
         return AMEDIA_ERROR_MALFORMED;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -348,8 +344,9 @@
     }
 
     buffer->set_range(0, frameSize);
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += 20000;  // Each frame is 20ms
@@ -366,22 +363,22 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
         1,
         "AMR Extractor",
         {
-           .v2 = [](
+           .v3 = [](
                     CDataSource *source,
                     float *confidence,
                     void **,
-                    FreeMetaFunc *) -> CreatorFuncV2 {
+                    FreeMetaFunc *) -> CreatorFuncV3 {
                 DataSourceHelper helper(source);
                 if (SniffAMR(&helper, nullptr, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractorV2* {
-                        return wrapV2(new AMRExtractor(new DataSourceHelper(source)));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new AMRExtractor(new DataSourceHelper(source)));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index 44b2cbd..b50ce81 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -29,12 +29,12 @@
 class String8;
 #define OFFSET_TABLE_LEN    300
 
-class AMRExtractor : public MediaExtractorPluginHelperV2 {
+class AMRExtractor : public MediaExtractorPluginHelperV3 {
 public:
     explicit AMRExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 83ea4c7..4bd933d 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
@@ -34,9 +33,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 4d0a4cc..3a3d051 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -10,7 +10,6 @@
     shared_libs: [
         "libbinder_ndk",
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
@@ -40,9 +39,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index d54aaef..22b96e5 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -36,7 +36,6 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MetaDataUtils.h>
-#include <media/stagefright/MediaBufferBase.h>
 #include <private/android_filesystem_config.h> // for AID_MEDIA
 #include <system/audio.h>
 
@@ -53,7 +52,7 @@
 
 class FLACParser;
 
-class FLACSource : public MediaTrackHelperV2 {
+class FLACSource : public MediaTrackHelperV3 {
 
 public:
     FLACSource(
@@ -66,7 +65,7 @@
     virtual media_status_t getFormat(AMediaFormat *meta);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~FLACSource();
@@ -125,12 +124,12 @@
     }
 
     // media buffers
-    void allocateBuffers();
+    void allocateBuffers(MediaBufferGroupHelperV3 *group);
     void releaseBuffers();
-    MediaBufferBase *readBuffer() {
+    MediaBufferHelperV3 *readBuffer() {
         return readBuffer(false, 0LL);
     }
-    MediaBufferBase *readBuffer(FLAC__uint64 sample) {
+    MediaBufferHelperV3 *readBuffer(FLAC__uint64 sample) {
         return readBuffer(true, sample);
     }
 
@@ -143,7 +142,7 @@
 
     // media buffers
     size_t mMaxBufferSize;
-    MediaBufferGroup *mGroup;
+    MediaBufferGroupHelperV3 *mGroup;
     void (*mCopy)(int16_t *dst, const int * src[kMaxChannels], unsigned nSamples, unsigned nChannels);
 
     // handle to underlying libFLAC parser
@@ -167,7 +166,7 @@
     FLAC__StreamDecoderErrorStatus mErrorStatus;
 
     status_t init();
-    MediaBufferBase *readBuffer(bool doSeek, FLAC__uint64 sample);
+    MediaBufferHelperV3 *readBuffer(bool doSeek, FLAC__uint64 sample);
 
     // no copy constructor or assignment
     FLACParser(const FLACParser &);
@@ -401,6 +400,7 @@
 
 // Copy samples from FLAC native 32-bit non-interleaved to 16-bit signed
 // or 32-bit float interleaved.
+// TODO: Consider moving to audio_utils.
 // These are candidates for optimization if needed.
 static void copyTo16Signed(
         short *dst,
@@ -408,10 +408,19 @@
         unsigned nSamples,
         unsigned nChannels,
         unsigned bitsPerSample) {
-    const unsigned leftShift = 16 - bitsPerSample;
-    for (unsigned i = 0; i < nSamples; ++i) {
-        for (unsigned c = 0; c < nChannels; ++c) {
-            *dst++ = src[c][i] << leftShift;
+    const int leftShift = 16 - (int)bitsPerSample; // cast to int to prevent unsigned overflow.
+    if (leftShift >= 0) {
+        for (unsigned i = 0; i < nSamples; ++i) {
+            for (unsigned c = 0; c < nChannels; ++c) {
+                *dst++ = src[c][i] << leftShift;
+            }
+        }
+    } else {
+        const int rightShift = -leftShift;
+        for (unsigned i = 0; i < nSamples; ++i) {
+            for (unsigned c = 0; c < nChannels; ++c) {
+                *dst++ = src[c][i] >> rightShift;
+            }
         }
     }
 }
@@ -514,8 +523,10 @@
         case 8:
         case 16:
         case 24:
+        case 32: // generally not expected for FLAC
             break;
         default:
+            // Note: internally the FLAC extractor supports 2-32 bits.
             ALOGE("unsupported bits per sample %u", getBitsPerSample());
             return NO_INIT;
         }
@@ -532,8 +543,11 @@
         case 48000:
         case 88200:
         case 96000:
+        case 176400:
+        case 192000:
             break;
         default:
+            // Note: internally we support arbitrary sample rates from 8kHz to 192kHz.
             ALOGE("unsupported sample rate %u", getSampleRate());
             return NO_INIT;
         }
@@ -562,12 +576,12 @@
     return OK;
 }
 
-void FLACParser::allocateBuffers()
+void FLACParser::allocateBuffers(MediaBufferGroupHelperV3 *group)
 {
     CHECK(mGroup == NULL);
-    mGroup = new MediaBufferGroup;
+    mGroup = group;
     mMaxBufferSize = getMaxBlockSize() * getChannels() * getOutputSampleSize();
-    mGroup->add_buffer(MediaBufferBase::Create(mMaxBufferSize));
+    mGroup->add_buffer(mMaxBufferSize);
 }
 
 void FLACParser::releaseBuffers()
@@ -577,7 +591,7 @@
     mGroup = NULL;
 }
 
-MediaBufferBase *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample)
+MediaBufferHelperV3 *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample)
 {
     mWriteRequested = true;
     mWriteCompleted = false;
@@ -614,7 +628,7 @@
     }
     // acquire a media buffer
     CHECK(mGroup != NULL);
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     status_t err = mGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return NULL;
@@ -641,8 +655,9 @@
     CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
     FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number;
     int64_t timeUs = (1000000LL * sampleNumber) / getSampleRate();
-    buffer->meta_data().setInt64(kKeyTime, timeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
     return buffer;
 }
 
@@ -676,7 +691,7 @@
     ALOGV("FLACSource::start");
 
     CHECK(!mStarted);
-    mParser->allocateBuffers();
+    mParser->allocateBuffers(mBufferGroup);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -704,9 +719,9 @@
 }
 
 media_status_t FLACSource::read(
-        MediaBufferBase **outBuffer, const ReadOptions *options)
+        MediaBufferHelperV3 **outBuffer, const ReadOptions *options)
 {
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     // process an optional seek request
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
@@ -760,7 +775,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *FLACExtractor::getTrack(size_t index)
+MediaTrackHelperV3 *FLACExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
@@ -816,22 +831,22 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-            EXTRACTORDEF_VERSION_CURRENT,
+            EXTRACTORDEF_VERSION_CURRENT + 1,
             UUID("1364b048-cc45-4fda-9934-327d0ebf9829"),
             1,
             "FLAC Extractor",
             {
-                .v2 = [](
+                .v3 = [](
                         CDataSource *source,
                         float *confidence,
                         void **,
-                        FreeMetaFunc *) -> CreatorFuncV2 {
+                        FreeMetaFunc *) -> CreatorFuncV3 {
                     DataSourceHelper helper(source);
                     if (SniffFLAC(&helper, confidence)) {
                         return [](
                                 CDataSource *source,
-                                void *) -> CMediaExtractorV2* {
-                            return wrapV2(new FLACExtractor(new DataSourceHelper(source)));};
+                                void *) -> CMediaExtractorV3* {
+                            return wrapV3(new FLACExtractor(new DataSourceHelper(source)));};
                     }
                     return NULL;
                 }
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 323307b..9604e4a 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -27,13 +27,13 @@
 
 class FLACParser;
 
-class FLACExtractor : public MediaExtractorPluginHelperV2 {
+class FLACExtractor : public MediaExtractorPluginHelperV3 {
 
 public:
     explicit FLACExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index c5df5c7..7d42e70 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
@@ -35,9 +34,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index cd39cec..43f394c 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -25,15 +25,14 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
 #include <libsonivox/eas_reverb.h>
 
 namespace android {
 
-// how many Sonivox output buffers to aggregate into one MediaBufferBase
+// how many Sonivox output buffers to aggregate into one MediaBuffer
 static const int NUM_COMBINE_BUFFERS = 4;
 
-class MidiSource : public MediaTrackHelperV2 {
+class MidiSource : public MediaTrackHelperV3 {
 
 public:
     MidiSource(
@@ -45,7 +44,7 @@
     virtual media_status_t getFormat(AMediaFormat *);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~MidiSource();
@@ -93,7 +92,7 @@
 
     CHECK(!mStarted);
     mStarted = true;
-    mEngine.allocateBuffers();
+    mEngine.allocateBuffers(mBufferGroup);
     return AMEDIA_OK;
 }
 
@@ -114,10 +113,10 @@
 }
 
 media_status_t MidiSource::read(
-        MediaBufferBase **outBuffer, const ReadOptions *options)
+        MediaBufferHelperV3 **outBuffer, const ReadOptions *options)
 {
     ALOGV("MidiSource::read");
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     // process an optional seek request
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
@@ -144,7 +143,6 @@
 MidiEngine::MidiEngine(CDataSource *dataSource,
         AMediaFormat *fileMetadata,
         AMediaFormat *trackMetadata) :
-            mGroup(NULL),
             mEasData(NULL),
             mEasHandle(NULL),
             mEasConfig(NULL),
@@ -194,7 +192,6 @@
     if (mEasData) {
         EAS_Shutdown(mEasData);
     }
-    delete mGroup;
     delete mIoWrapper;
 }
 
@@ -202,22 +199,20 @@
     return mIsInitialized ? OK : UNKNOWN_ERROR;
 }
 
-status_t MidiEngine::allocateBuffers() {
+status_t MidiEngine::allocateBuffers(MediaBufferGroupHelperV3 *group) {
     // select reverb preset and enable
     EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
     EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
 
-    mGroup = new MediaBufferGroup;
     int bufsize = sizeof(EAS_PCM)
             * mEasConfig->mixBufferSize * mEasConfig->numChannels * NUM_COMBINE_BUFFERS;
     ALOGV("using %d byte buffer", bufsize);
-    mGroup->add_buffer(MediaBufferBase::Create(bufsize));
+    mGroup = group;
+    mGroup->add_buffer(bufsize);
     return OK;
 }
 
 status_t MidiEngine::releaseBuffers() {
-    delete mGroup;
-    mGroup = NULL;
     return OK;
 }
 
@@ -227,13 +222,13 @@
     return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR;
 }
 
-MediaBufferBase* MidiEngine::readBuffer() {
+MediaBufferHelperV3* MidiEngine::readBuffer() {
     EAS_STATE state;
     EAS_State(mEasData, mEasHandle, &state);
     if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
         return NULL;
     }
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     status_t err = mGroup->acquire_buffer(&buffer);
     if (err != OK) {
         ALOGE("readBuffer: no buffer");
@@ -242,7 +237,9 @@
     EAS_I32 timeMs;
     EAS_GetLocation(mEasData, mEasHandle, &timeMs);
     int64_t timeUs = 1000ll * timeMs;
-    buffer->meta_data().setInt64(kKeyTime, timeUs);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     EAS_PCM* p = (EAS_PCM*) buffer->data();
     int numBytesOutput = 0;
@@ -289,7 +286,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *MidiExtractor::getTrack(size_t index)
+MediaTrackHelperV3 *MidiExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
@@ -334,21 +331,21 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("ef6cca0a-f8a2-43e6-ba5f-dfcd7c9a7ef2"),
         1,
         "MIDI Extractor",
         {
-            .v2 = [](
+            .v3 = [](
                 CDataSource *source,
                 float *confidence,
                 void **,
-                FreeMetaFunc *) -> CreatorFuncV2 {
+                FreeMetaFunc *) -> CreatorFuncV3 {
                 if (SniffMidi(source, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractorV2* {
-                        return wrapV2(new MidiExtractor(source));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new MidiExtractor(source));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 412d6eb..ad345b8 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -38,26 +38,26 @@
 
     status_t initCheck();
 
-    status_t allocateBuffers();
+    status_t allocateBuffers(MediaBufferGroupHelperV3 *group);
     status_t releaseBuffers();
     status_t seekTo(int64_t positionUs);
-    MediaBufferBase* readBuffer();
+    MediaBufferHelperV3* readBuffer();
 private:
     MidiIoWrapper *mIoWrapper;
-    MediaBufferGroup *mGroup;
+    MediaBufferGroupHelperV3 *mGroup;
     EAS_DATA_HANDLE mEasData;
     EAS_HANDLE mEasHandle;
     const S_EAS_LIB_CONFIG* mEasConfig;
     bool mIsInitialized;
 };
 
-class MidiExtractor : public MediaExtractorPluginHelperV2 {
+class MidiExtractor : public MediaExtractorPluginHelperV3 {
 
 public:
     explicit MidiExtractor(CDataSource *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index ae108ec..8d028e1 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -41,9 +41,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 1025c46..4e2f248 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -12,14 +12,13 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
-        "libstagefright_foundation",
     ],
 
     static_libs: [
         "libutils",
         "libstagefright_id3",
+        "libstagefright_foundation",
     ],
 
     name: "libmp3extractor",
@@ -40,9 +39,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 0e1ffb4..7abec54 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -207,7 +207,7 @@
     return valid;
 }
 
-class MP3Source : public MediaTrackHelperV2 {
+class MP3Source : public MediaTrackHelperV3 {
 public:
     MP3Source(
             AMediaFormat *meta, DataSourceHelper *source,
@@ -220,7 +220,7 @@
     virtual media_status_t getFormat(AMediaFormat *meta);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~MP3Source();
@@ -235,7 +235,6 @@
     int64_t mCurrentTimeUs;
     bool mStarted;
     MP3Seeker *mSeeker;
-    MediaBufferGroup *mGroup;
 
     int64_t mBasisTimeUs;
     int64_t mSamplesRead;
@@ -414,7 +413,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-MediaTrackHelperV2 *MP3Extractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MP3Extractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -455,7 +454,6 @@
       mCurrentTimeUs(0),
       mStarted(false),
       mSeeker(seeker),
-      mGroup(NULL),
       mBasisTimeUs(0),
       mSamplesRead(0) {
 }
@@ -469,9 +467,7 @@
 media_status_t MP3Source::start() {
     CHECK(!mStarted);
 
-    mGroup = new MediaBufferGroup;
-
-    mGroup->add_buffer(MediaBufferBase::Create(kMaxFrameSize));
+    mBufferGroup->add_buffer(kMaxFrameSize);
 
     mCurrentPos = mFirstFramePos;
     mCurrentTimeUs = 0;
@@ -487,9 +483,6 @@
 media_status_t MP3Source::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
 
     return AMEDIA_OK;
@@ -500,7 +493,7 @@
 }
 
 media_status_t MP3Source::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -530,8 +523,8 @@
         mSamplesRead = 0;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -597,8 +590,9 @@
 
     buffer->set_range(0, frame_size);
 
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mCurrentPos += frame_size;
 
@@ -674,14 +668,14 @@
     return AMEDIA_OK;
 }
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *meta) {
     Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
-    return wrapV2(new MP3Extractor(new DataSourceHelper(source), metaData));
+    return wrapV3(new MP3Extractor(new DataSourceHelper(source), metaData));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source, float *confidence, void **meta,
         FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
@@ -718,11 +712,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
         1, // version
         "MP3 Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 22547e2..fe72cff 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -32,13 +32,13 @@
 class String8;
 struct Mp3Meta;
 
-class MP3Extractor : public MediaExtractorPluginHelperV2 {
+class MP3Extractor : public MediaExtractorPluginHelperV3 {
 public:
     MP3Extractor(DataSourceHelper *source, Mp3Meta *meta);
     ~MP3Extractor();
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/extractors/mp4/AC4Parser.cpp
index a95c2db..59a2e9b 100644
--- a/media/extractors/mp4/AC4Parser.cpp
+++ b/media/extractors/mp4/AC4Parser.cpp
@@ -310,13 +310,13 @@
                 pres_bytes += mBitReader.getBits(16);
             }
             ALOGV("%u: pres_bytes = %u\n", presentation, pres_bytes);
-            if (presentation_version > 1) {
+            if (presentation_version > 2) {
                 CHECK_BITS_LEFT(pres_bytes * 8);
                 mBitReader.skipBits(pres_bytes * 8);
                 continue;
             }
-            // ac4_presentation_v0_dsi() and ac4_presentation_v1_dsi() both
-            // start with a presentation_config of 5 bits
+            // ac4_presentation_v0_dsi(), ac4_presentation_v1_dsi() and ac4_presentation_v2_dsi()
+            // all start with a presentation_config of 5 bits
             CHECK_BITS_LEFT(5);
             presentation_config = mBitReader.getBits(5);
             b_single_substream_group = (presentation_config == 0x1f);
@@ -363,7 +363,7 @@
             uint32_t dsi_frame_rate_multiply_info = mBitReader.getBits(2);
             ALOGV("%u: dsi_frame_rate_multiply_info = %d\n", presentation,
                 dsi_frame_rate_multiply_info);
-            if (ac4_dsi_version == 1 && presentation_version == 1) {
+            if (ac4_dsi_version == 1 && (presentation_version == 1 || presentation_version == 2)) {
                 CHECK_BITS_LEFT(2);
                 uint32_t dsi_frame_rate_fraction_info = mBitReader.getBits(2);
                 ALOGV("%u: dsi_frame_rate_fraction_info = %d\n", presentation,
@@ -386,7 +386,7 @@
                 ALOGV("%u: b_presentation_channel_coded = %s\n", presentation,
                     BOOLSTR(b_presentation_channel_coded));
                 if (b_presentation_channel_coded) {
-                    if (presentation_version == 1) {
+                    if (presentation_version == 1 || presentation_version == 2) {
                         CHECK_BITS_LEFT(5);
                         uint32_t dsi_presentation_ch_mode = mBitReader.getBits(5);
                         mPresentations[presentation].mChannelMode = dsi_presentation_ch_mode;
@@ -411,7 +411,7 @@
                     ALOGV("%u: presentation_channel_mask_v1 = 0x%06x\n", presentation,
                         presentation_channel_mask_v1);
                 }
-                if (presentation_version == 1) {
+                if (presentation_version == 1 || presentation_version == 2) {
                     CHECK_BITS_LEFT(1);
                     bool b_presentation_core_differs = (mBitReader.getBits(1) == 1);
                     ALOGV("%u: b_presentation_core_differs = %s\n", presentation,
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 47dc718..91de353 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -48,9 +48,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 337ff2a..9fb2e35 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -2733,8 +2733,7 @@
 
     // + 4-byte type
     offset += 4;
-    // at least for AC4 DSI v1 this is big enough
-    const uint32_t kAC4SpecificBoxPayloadSize = 256;
+    const uint32_t kAC4SpecificBoxPayloadSize = 1176;
     uint8_t chunk[kAC4SpecificBoxPayloadSize];
     ssize_t dsiSize = size - 8; // size of box - size and type fields
     if (dsiSize >= (ssize_t)kAC4SpecificBoxPayloadSize ||
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 40314dc..38c86eb 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -52,9 +52,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index c6deb18..01acb2c 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -38,9 +38,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 185bb32..7e89271 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -9,7 +9,6 @@
     shared_libs: [
         "libbinder_ndk",
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
@@ -37,9 +36,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 86500ef..1f0aae5 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -22,9 +22,7 @@
 
 #include <android/binder_ibinder.h> // for AIBinder_getCallingUid
 #include <audio_utils/primitives.h>
-#include <media/DataSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
@@ -68,7 +66,7 @@
     return ptr[1] << 8 | ptr[0];
 }
 
-struct WAVSource : public MediaTrackHelperV2 {
+struct WAVSource : public MediaTrackHelperV3 {
     WAVSource(
             DataSourceHelper *dataSource,
             AMediaFormat *meta,
@@ -81,7 +79,7 @@
     virtual media_status_t getFormat(AMediaFormat *meta);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
     virtual bool supportNonblockingRead() { return true; }
 
@@ -101,7 +99,6 @@
     off64_t mOffset;
     size_t mSize;
     bool mStarted;
-    MediaBufferGroup *mGroup;
     off64_t mCurrentPos;
 
     WAVSource(const WAVSource &);
@@ -134,7 +131,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *WAVExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *WAVExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index > 0) {
         return NULL;
     }
@@ -379,8 +376,7 @@
       mOutputFloat(outputFloat),
       mOffset(offset),
       mSize(size),
-      mStarted(false),
-      mGroup(NULL) {
+      mStarted(false) {
     CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate));
     CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mNumChannels));
     CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &mBitsPerSample));
@@ -398,7 +394,9 @@
     CHECK(!mStarted);
 
     // some WAV files may have large audio buffers that use shared memory transfer.
-    mGroup = new MediaBufferGroup(4 /* buffers */, kMaxFrameSize);
+    if (!mBufferGroup->init(4 /* buffers */, kMaxFrameSize)) {
+        return AMEDIA_ERROR_UNKNOWN;
+    }
 
     mCurrentPos = mOffset;
 
@@ -412,9 +410,6 @@
 
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
 
     return AMEDIA_OK;
@@ -433,10 +428,10 @@
 }
 
 media_status_t WAVSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
-    if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) {
+    if (options != nullptr && options->getNonBlocking() && !mBufferGroup->has_buffers()) {
         return AMEDIA_ERROR_WOULD_BLOCK;
     }
 
@@ -459,10 +454,10 @@
         mCurrentPos = pos + mOffset;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    media_status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
-        return AMEDIA_ERROR_UNKNOWN;
+        return err;
     }
 
     // maxBytesToRead may be reduced so that in-place data conversion will fit in buffer size.
@@ -573,9 +568,10 @@
                 / (mNumChannels * bytesPerSample) / mSampleRate;
     }
 
-    buffer->meta_data().setInt64(kKeyTime, timeStampUs);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeStampUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
     mCurrentPos += n;
 
     *out = buffer;
@@ -585,13 +581,13 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *) {
-    return wrapV2(new WAVExtractor(new DataSourceHelper(source)));
+    return wrapV3(new WAVExtractor(new DataSourceHelper(source)));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source,
         float *confidence,
         void **,
@@ -625,11 +621,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
         1, // version
         "WAV Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index ce34881..9b7dfde 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -29,12 +29,12 @@
 struct CDataSource;
 class String8;
 
-class WAVExtractor : public MediaExtractorPluginHelperV2 {
+class WAVExtractor : public MediaExtractorPluginHelperV3 {
 public:
     explicit WAVExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/libaaudio/src/binding/IAAudioService.cpp b/media/libaaudio/src/binding/IAAudioService.cpp
index 620edc7..9b32543 100644
--- a/media/libaaudio/src/binding/IAAudioService.cpp
+++ b/media/libaaudio/src/binding/IAAudioService.cpp
@@ -72,7 +72,6 @@
             ALOGE("BpAAudioService::client transact(OPEN_STREAM) readInt %d", err);
             return AAudioConvert_androidToAAudioResult(err);
         } else if (stream < 0) {
-            ALOGE("BpAAudioService::client OPEN_STREAM passed stream %d", stream);
             return stream;
         }
         err = configurationOutput.readFromParcel(&reply);
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 0a8021a..fffcda0 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -131,7 +131,6 @@
         mServiceStreamHandle = mServiceInterface.openStream(request, configurationOutput);
     }
     if (mServiceStreamHandle < 0) {
-        ALOGE("%s - openStream() returned %d", __func__, mServiceStreamHandle);
         return mServiceStreamHandle;
     }
 
@@ -693,7 +692,6 @@
     }
 
     aaudio_result_t result = mAudioEndpoint.setBufferSizeInFrames(adjustedFrames, &actualFrames);
-    ALOGD("setBufferSize() req = %d => %d", requestedFrames, actualFrames);
     if (result < 0) {
         return result;
     } else {
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index e272f2a..2fb3986 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -241,7 +241,7 @@
 {
     AudioStream *audioStream = nullptr;
     // Please leave these logs because they are very helpful when debugging.
-    ALOGD("AAudioStreamBuilder_openStream() called ----------------------------------------");
+    ALOGD("%s() called ----------------------------------------", __func__);
     AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
     aaudio_result_t result = streamBuilder->build(&audioStream);
     ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
@@ -269,7 +269,7 @@
 {
     aaudio_result_t result = AAUDIO_ERROR_NULL;
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("AAudioStream_close(%p) called ---------------", stream);
+    ALOGD("%s(%p) called ---------------", __func__, stream);
     if (audioStream != nullptr) {
         result = audioStream->safeClose();
         // Close will only fail if called illegally, for example, from a callback.
@@ -284,7 +284,7 @@
     // We're potentially freeing `stream` above, so its use here makes some
     // static analysis tools unhappy. Casting to uintptr_t helps assure
     // said tools that we're not doing anything bad here.
-    ALOGD("AAudioStream_close(%#" PRIxPTR ") returned %d ---------",
+    ALOGD("%s(%#" PRIxPTR ") returned %d ---------", __func__,
           reinterpret_cast<uintptr_t>(stream), result);
     return result;
 }
@@ -292,30 +292,30 @@
 AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("AAudioStream_requestStart(%p) called --------------", stream);
+    ALOGD("%s(%p) called --------------", __func__, stream);
     aaudio_result_t result = audioStream->systemStart();
-    ALOGD("AAudioStream_requestStart(%p) returned %d ---------", stream, result);
+    ALOGD("%s(%p) returned %d ---------", __func__, stream, result);
     return result;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("AAudioStream_requestPause(%p)", stream);
+    ALOGD("%s(%p) called", __func__, stream);
     return audioStream->systemPause();
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("AAudioStream_requestFlush(%p)", stream);
+    ALOGD("%s(%p) called", __func__, stream);
     return audioStream->safeFlush();
 }
 
 AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    ALOGD("AAudioStream_requestStop(%p)", stream);
+    ALOGD("%s(%p) called", __func__, stream);
     return audioStream->systemStop();
 }
 
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 358021b..391af29 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -37,7 +37,6 @@
 }
 
 AudioStream::~AudioStream() {
-    ALOGD("destroying %p, state = %s", this, AAudio_convertStreamStateToText(getState()));
     // If the stream is deleted when OPEN or in use then audio resources will leak.
     // This would indicate an internal error. So we want to find this ASAP.
     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
diff --git a/media/libaaudio/src/fifo/FifoControllerBase.cpp b/media/libaaudio/src/fifo/FifoControllerBase.cpp
index 9885cb0..66e247f 100644
--- a/media/libaaudio/src/fifo/FifoControllerBase.cpp
+++ b/media/libaaudio/src/fifo/FifoControllerBase.cpp
@@ -38,7 +38,7 @@
 
 fifo_frames_t FifoControllerBase::getReadIndex() {
     // % works with non-power of two sizes
-    return (fifo_frames_t) (getReadCounter() % mCapacity);
+    return (fifo_frames_t) ((uint64_t)getReadCounter() % mCapacity);
 }
 
 void FifoControllerBase::advanceReadIndex(fifo_frames_t numFrames) {
@@ -51,7 +51,7 @@
 
 fifo_frames_t FifoControllerBase::getWriteIndex() {
     // % works with non-power of two sizes
-    return (fifo_frames_t) (getWriteCounter() % mCapacity);
+    return (fifo_frames_t) ((uint64_t)getWriteCounter() % mCapacity);
 }
 
 void FifoControllerBase::advanceWriteIndex(fifo_frames_t numFrames) {
diff --git a/media/libaaudio/tests/test_atomic_fifo.cpp b/media/libaaudio/tests/test_atomic_fifo.cpp
index a09b74c..130ef43 100644
--- a/media/libaaudio/tests/test_atomic_fifo.cpp
+++ b/media/libaaudio/tests/test_atomic_fifo.cpp
@@ -23,12 +23,12 @@
 #include "fifo/FifoController.h"
 
 using android::fifo_frames_t;
+using android::fifo_counter_t;
 using android::FifoController;
 using android::FifoBuffer;
 using android::WrappingBuffer;
 
-//void foo() {
-TEST(test_fifi_controller, fifo_indices) {
+TEST(test_fifo_controller, fifo_indices) {
     // Values are arbitrary primes designed to trigger edge cases.
     constexpr int capacity = 83;
     constexpr int threshold = 47;
@@ -73,18 +73,59 @@
     ASSERT_EQ(threshold - advance2, fifoController.getEmptyFramesAvailable());
 }
 
+TEST(test_fifo_controller, fifo_wrap_around_zero) {
+    constexpr int capacity = 7; // arbitrary prime
+    constexpr int threshold = capacity;
+    FifoController fifoController(capacity, threshold);
+    ASSERT_EQ(capacity, fifoController.getCapacity());
+    ASSERT_EQ(threshold, fifoController.getThreshold());
+
+    fifoController.setReadCounter(-10); // a bit less than negative capacity
+    for (int i = 0; i < 20; i++) {
+        EXPECT_EQ(i - 10, fifoController.getReadCounter());
+        EXPECT_GE(fifoController.getReadIndex(), 0);
+        EXPECT_LT(fifoController.getReadIndex(), capacity);
+        fifoController.advanceReadIndex(1);
+    }
+
+    fifoController.setWriteCounter(-10);
+    for (int i = 0; i < 20; i++) {
+        EXPECT_EQ(i - 10, fifoController.getWriteCounter());
+        EXPECT_GE(fifoController.getWriteIndex(), 0);
+        EXPECT_LT(fifoController.getWriteIndex(), capacity);
+        fifoController.advanceWriteIndex(1);
+    }
+}
+
+
 // TODO consider using a template for other data types.
+
+// Create a big array and then use a region in the middle for the  unit tests.
+// Then we can scan the rest of the array to see if it got clobbered.
+static constexpr fifo_frames_t kBigArraySize = 1024;
+static constexpr fifo_frames_t kFifoDataOffset = 128; // starting index of FIFO data
+static constexpr int16_t       kSafeDataValue = 0x7654; // original value of BigArray
+
 class TestFifoBuffer {
 public:
     explicit TestFifoBuffer(fifo_frames_t capacity, fifo_frames_t threshold = 0)
-        : mFifoBuffer(sizeof(int16_t), capacity) {
+        : mFifoBuffer(sizeof(int16_t), capacity,
+                      &mReadIndex,
+                      &mWriteIndex,
+                      &mVeryBigArray[kFifoDataOffset]) // address of start of FIFO data
+    {
+
+        // Assume a frame is one int16_t.
         // For reading and writing.
-        mData = new int16_t[capacity];
         if (threshold <= 0) {
             threshold = capacity;
         }
         mFifoBuffer.setThreshold(threshold);
         mThreshold = threshold;
+
+        for (fifo_frames_t i = 0; i < kBigArraySize; i++) {
+            mVeryBigArray[i] = kSafeDataValue;
+        }
     }
 
     void checkMisc() {
@@ -92,26 +133,70 @@
         ASSERT_EQ(mThreshold, mFifoBuffer.getThreshold());
     }
 
+    void verifyAddressInRange(void *p, void *valid, size_t numBytes) {
+        uintptr_t p_int = (uintptr_t) p;
+        uintptr_t valid_int = (uintptr_t) valid;
+        EXPECT_GE(p_int, valid_int);
+        EXPECT_LT(p_int, (valid_int + numBytes));
+    }
+
+    void verifyStorageIntegrity() {
+        for (fifo_frames_t i = 0; i < kFifoDataOffset; i++) {
+            EXPECT_EQ(mVeryBigArray[i], kSafeDataValue);
+        }
+        fifo_frames_t firstFrameAfter = kFifoDataOffset + mFifoBuffer.getBufferCapacityInFrames();
+        for (fifo_frames_t i = firstFrameAfter; i < kBigArraySize; i++) {
+            EXPECT_EQ(mVeryBigArray[i], kSafeDataValue);
+        }
+    }
+
     // Verify that the available frames in each part add up correctly.
-    void checkWrappingBuffer() {
+    void verifyWrappingBuffer() {
         WrappingBuffer wrappingBuffer;
+
+
+        // Does the sum of the two parts match the available value returned?
+        // For EmptyRoom
         fifo_frames_t framesAvailable =
                 mFifoBuffer.getEmptyFramesAvailable();
         fifo_frames_t wrapAvailable = mFifoBuffer.getEmptyRoomAvailable(&wrappingBuffer);
         EXPECT_EQ(framesAvailable, wrapAvailable);
         fifo_frames_t bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1];
         EXPECT_EQ(framesAvailable, bothAvailable);
-
+        // For FullData
         framesAvailable =
                 mFifoBuffer.getFullFramesAvailable();
         wrapAvailable = mFifoBuffer.getFullDataAvailable(&wrappingBuffer);
         EXPECT_EQ(framesAvailable, wrapAvailable);
         bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1];
         EXPECT_EQ(framesAvailable, bothAvailable);
+
+        // Are frame counts in legal range?
+        fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames();
+        EXPECT_GE(wrappingBuffer.numFrames[0], 0);
+        EXPECT_LE(wrappingBuffer.numFrames[0], capacity);
+        EXPECT_GE(wrappingBuffer.numFrames[1], 0);
+        EXPECT_LE(wrappingBuffer.numFrames[1], capacity);
+
+        // Are addresses within the FIFO data area?
+        size_t validBytes = capacity * sizeof(int16_t);
+        if (wrappingBuffer.numFrames[0]) {
+            verifyAddressInRange(wrappingBuffer.data[0], mFifoStorage, validBytes);
+            uint8_t *last = ((uint8_t *)wrappingBuffer.data[0])
+                            + mFifoBuffer.convertFramesToBytes(wrappingBuffer.numFrames[0]) - 1;
+            verifyAddressInRange(last, mFifoStorage, validBytes);
+        }
+        if (wrappingBuffer.numFrames[1]) {
+            verifyAddressInRange(wrappingBuffer.data[1], mFifoStorage, validBytes);
+            uint8_t *last = ((uint8_t *)wrappingBuffer.data[1])
+                            + mFifoBuffer.convertFramesToBytes(wrappingBuffer.numFrames[1]) - 1;
+            verifyAddressInRange(last, mFifoStorage, validBytes);
+        }
+
     }
 
     // Write data but do not overflow.
-    void writeData(fifo_frames_t numFrames) {
+    void writeMultipleDataFrames(fifo_frames_t numFrames) {
         fifo_frames_t framesAvailable =
                 mFifoBuffer.getEmptyFramesAvailable();
         fifo_frames_t framesToWrite = std::min(framesAvailable, numFrames);
@@ -122,8 +207,8 @@
         ASSERT_EQ(framesToWrite, actual);
     }
 
-    // Read data but do not underflow.
-    void verifyData(fifo_frames_t numFrames) {
+    // Read whatever data is available, Do not underflow.
+    void verifyMultipleDataFrames(fifo_frames_t numFrames) {
         fifo_frames_t framesAvailable =
                 mFifoBuffer.getFullFramesAvailable();
         fifo_frames_t framesToRead = std::min(framesAvailable, numFrames);
@@ -134,20 +219,35 @@
         }
     }
 
+    // Read specified number of frames
+    void verifyRequestedData(fifo_frames_t numFrames) {
+        fifo_frames_t framesAvailable =
+                mFifoBuffer.getFullFramesAvailable();
+        ASSERT_LE(numFrames, framesAvailable);
+        fifo_frames_t framesToRead = std::min(framesAvailable, numFrames);
+        fifo_frames_t actual = mFifoBuffer.read(mData, framesToRead);
+        ASSERT_EQ(actual, numFrames);
+        for (int i = 0; i < actual; i++) {
+            ASSERT_EQ(mNextVerifyIndex++, mData[i]);
+        }
+    }
+
     // Wrap around the end of the buffer.
     void checkWrappingWriteRead() {
         constexpr int frames1 = 43;
         constexpr int frames2 = 15;
 
-        writeData(frames1);
-        checkWrappingBuffer();
-        verifyData(frames1);
-        checkWrappingBuffer();
+        writeMultipleDataFrames(frames1);
+        verifyWrappingBuffer();
+        verifyRequestedData(frames1);
+        verifyWrappingBuffer();
 
-        writeData(frames2);
-        checkWrappingBuffer();
-        verifyData(frames2);
-        checkWrappingBuffer();
+        writeMultipleDataFrames(frames2);
+        verifyWrappingBuffer();
+        verifyRequestedData(frames2);
+        verifyWrappingBuffer();
+
+        verifyStorageIntegrity();
     }
 
     // Write and Read a specific amount of data.
@@ -156,10 +256,12 @@
         // Wrap around with the smaller region in the second half.
         const int frames1 = capacity - 4;
         const int frames2 = 7; // arbitrary, small
-        writeData(frames1);
-        verifyData(frames1);
-        writeData(frames2);
-        verifyData(frames2);
+        writeMultipleDataFrames(frames1);
+        verifyRequestedData(frames1);
+        writeMultipleDataFrames(frames2);
+        verifyRequestedData(frames2);
+
+        verifyStorageIntegrity();
     }
 
     // Write and Read a specific amount of data.
@@ -168,10 +270,12 @@
         // Wrap around with the larger region in the second half.
         const int frames1 = capacity - 4;
         const int frames2 = capacity - 9; // arbitrary, large
-        writeData(frames1);
-        verifyData(frames1);
-        writeData(frames2);
-        verifyData(frames2);
+        writeMultipleDataFrames(frames1);
+        verifyRequestedData(frames1);
+        writeMultipleDataFrames(frames2);
+        verifyRequestedData(frames2);
+
+        verifyStorageIntegrity();
     }
 
     // Randomly read or write up to the maximum amount of data.
@@ -180,30 +284,67 @@
             fifo_frames_t framesEmpty =
                     mFifoBuffer.getEmptyFramesAvailable();
             fifo_frames_t numFrames = (fifo_frames_t)(drand48() * framesEmpty);
-            writeData(numFrames);
+            writeMultipleDataFrames(numFrames);
 
             fifo_frames_t framesFull =
                     mFifoBuffer.getFullFramesAvailable();
             numFrames = (fifo_frames_t)(drand48() * framesFull);
-            verifyData(numFrames);
+            verifyMultipleDataFrames(numFrames);
         }
+
+        verifyStorageIntegrity();
+    }
+
+    // Write and Read a specific amount of data.
+    void checkNegativeCounters() {
+        fifo_counter_t counter = -9876;
+        mFifoBuffer.setWriteCounter(counter);
+        mFifoBuffer.setReadCounter(counter);
+        checkWrappingWriteRead();
+    }
+
+    // Wrap over the boundary at 0x7FFFFFFFFFFFFFFF
+    // Note that the behavior of a signed overflow is technically undefined.
+    void checkHalfWrap() {
+        fifo_counter_t counter = INT64_MAX - 10;
+        mFifoBuffer.setWriteCounter(counter);
+        mFifoBuffer.setReadCounter(counter);
+        ASSERT_GT(mFifoBuffer.getWriteCounter(), 0);
+        checkWrappingWriteRead();
+        ASSERT_LT(mFifoBuffer.getWriteCounter(), 0); // did we wrap past INT64_MAX?
+    }
+
+    // Wrap over the boundary at 0xFFFFFFFFFFFFFFFF
+    void checkFullWrap() {
+        fifo_counter_t counter = -10;
+        mFifoBuffer.setWriteCounter(counter);
+        mFifoBuffer.setReadCounter(counter);
+        ASSERT_LT(mFifoBuffer.getWriteCounter(), 0);
+        writeMultipleDataFrames(20);
+        ASSERT_GT(mFifoBuffer.getWriteCounter(), 0); // did we wrap past zero?
+        verifyStorageIntegrity();
     }
 
     FifoBuffer     mFifoBuffer;
-    int16_t       *mData;
     fifo_frames_t  mNextWriteIndex = 0;
     fifo_frames_t  mNextVerifyIndex = 0;
     fifo_frames_t  mThreshold;
+
+    fifo_counter_t mReadIndex = 0;
+    fifo_counter_t mWriteIndex = 0;
+    int16_t        mVeryBigArray[kBigArraySize]; // Use the middle of this array for the FIFO.
+    int16_t       *mFifoStorage = &mVeryBigArray[kFifoDataOffset]; // Start here for storage.
+    int16_t        mData[kBigArraySize]{};
 };
 
-TEST(test_fifo_buffer, fifo_read_write) {
+TEST(test_fifo_buffer, fifo_write_read) {
     constexpr int capacity = 51; // arbitrary
     TestFifoBuffer tester(capacity);
     tester.checkMisc();
     tester.checkWriteRead();
 }
 
-TEST(test_fifo_buffer, fifo_wrapping_read_write) {
+TEST(test_fifo_buffer, fifo_wrapping_write_read) {
     constexpr int capacity = 59; // arbitrary, a little bigger this time
     TestFifoBuffer tester(capacity);
     tester.checkWrappingWriteRead();
@@ -227,3 +368,21 @@
     TestFifoBuffer tester(capacity, threshold);
     tester.checkRandomWriteRead();
 }
+
+TEST(test_fifo_buffer, fifo_negative_counters) {
+    constexpr int capacity = 49; // arbitrary
+    TestFifoBuffer tester(capacity);
+    tester.checkNegativeCounters();
+}
+
+TEST(test_fifo_buffer, fifo_half_wrap) {
+    constexpr int capacity = 57; // arbitrary
+    TestFifoBuffer tester(capacity);
+    tester.checkHalfWrap();
+}
+
+TEST(test_fifo_buffer, fifo_full_wrap) {
+    constexpr int capacity = 57; // arbitrary
+    TestFifoBuffer tester(capacity);
+    tester.checkFullWrap();
+}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 038c854..3223647 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -211,7 +211,7 @@
         mBufferMemory.clear();
         IPCThreadState::self()->flushCommands();
         ALOGV("%s(%d): releasing session id %d",
-                __func__, mId, mSessionId);
+                __func__, mPortId, mSessionId);
         AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/);
     }
 }
@@ -239,7 +239,7 @@
     pid_t callingPid;
     pid_t myPid;
 
-    // Note mId is not valid until the track is created, so omit mId in ALOG for set.
+    // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
     ALOGV("%s(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
           "uid %d, pid %d",
@@ -356,7 +356,7 @@
     // create the IAudioRecord
     status = createRecord_l(0 /*epoch*/, mOpPackageName);
 
-    ALOGV("%s(%d): status %d", __func__, mId, status);
+    ALOGV("%s(%d): status %d", __func__, mPortId, status);
 
     if (status != NO_ERROR) {
         if (mAudioRecordThread != 0) {
@@ -393,7 +393,7 @@
 
 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
 {
-    ALOGV("%s(%d): sync event %d trigger session %d", __func__, mId, event, triggerSession);
+    ALOGV("%s(%d): sync event %d trigger session %d", __func__, mPortId, event, triggerSession);
 
     AutoMutex lock(mLock);
     if (mActive) {
@@ -434,7 +434,7 @@
 
     if (status != NO_ERROR) {
         mActive = false;
-        ALOGE("%s(%d): status %d", __func__, mId, status);
+        ALOGE("%s(%d): status %d", __func__, mPortId, status);
     } else {
         sp<AudioRecordThread> t = mAudioRecordThread;
         if (t != 0) {
@@ -458,7 +458,7 @@
 void AudioRecord::stop()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): mActive:%d\n", __func__, mId, mActive);
+    ALOGV("%s(%d): mActive:%d\n", __func__, mPortId, mActive);
     if (!mActive) {
         return;
     }
@@ -638,7 +638,7 @@
 
     result.append(" AudioRecord::dump\n");
     result.appendFormat("  id(%d) status(%d), active(%d), session Id(%d)\n",
-                        mId, mStatus, mActive, mSessionId);
+                        mPortId, mStatus, mActive, mSessionId);
     result.appendFormat("  flags(%#x), req. flags(%#x), audio source(%d)\n",
                         mFlags, mOrigFlags, mAttributes.source);
     result.appendFormat("  format(%#x), channel mask(%#x), channel count(%u), sample rate(%u)\n",
@@ -680,7 +680,7 @@
     status_t status;
 
     if (audioFlinger == 0) {
-        ALOGE("%s(%d): Could not get audioflinger", __func__, mId);
+        ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -708,7 +708,7 @@
             (mTransfer == TRANSFER_OBTAIN);
         if (!useCaseAllowed) {
             ALOGW("%s(%d): AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
-                  __func__, mId,
+                  __func__, mPortId,
                   convertTransferToText(mTransfer));
             mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
                     AUDIO_INPUT_FLAG_RAW));
@@ -744,7 +744,7 @@
 
     if (status != NO_ERROR) {
         ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
-              __func__, mId, status);
+              __func__, mPortId, status);
         goto exit;
     }
     ALOG_ASSERT(record != 0);
@@ -755,7 +755,7 @@
     mAwaitBoost = false;
     if (output.flags & AUDIO_INPUT_FLAG_FAST) {
         ALOGI("%s(%d): AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu",
-              __func__, mId,
+              __func__, mPortId,
               mReqFrameCount, output.frameCount);
         mAwaitBoost = true;
     }
@@ -765,13 +765,13 @@
     mSampleRate = output.sampleRate;
 
     if (output.cblk == 0) {
-        ALOGE("%s(%d): Could not get control block", __func__, mId);
+        ALOGE("%s(%d): Could not get control block", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
     iMemPointer = output.cblk ->pointer();
     if (iMemPointer == NULL) {
-        ALOGE("%s(%d): Could not get control block pointer", __func__, mId);
+        ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -786,7 +786,7 @@
     } else {
         buffers = output.buffers->pointer();
         if (buffers == NULL) {
-            ALOGE("%s(%d): Could not get buffer pointer", __func__, mId);
+            ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
             goto exit;
         }
@@ -800,14 +800,14 @@
     mAudioRecord = record;
     mCblkMemory = output.cblk;
     mBufferMemory = output.buffers;
-    mId = output.trackId;
+    mPortId = output.portId;
     IPCThreadState::self()->flushCommands();
 
     mCblk = cblk;
     // note that output.frameCount is the (possibly revised) value of mReqFrameCount
     if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
         ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
-              __func__, mId,
+              __func__, mPortId,
               mReqFrameCount,  output.frameCount);
     }
 
@@ -815,7 +815,7 @@
     // The computation is done on server side.
     if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
         ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
-                __func__, mId,
+                __func__, mPortId,
                 mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
     }
     mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
@@ -883,7 +883,7 @@
         timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
-        ALOGE("%s(%d): invalid waitCount %d", __func__, mId, waitCount);
+        ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
         requested = NULL;
     }
     return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
@@ -993,7 +993,7 @@
         // sanity-check. user is most-likely passing an error code, and it would
         // make the return value ambiguous (actualSize vs error).
         ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",
-                __func__, mId, buffer, userSize, userSize);
+                __func__, mPortId, buffer, userSize, userSize);
         return BAD_VALUE;
     }
 
@@ -1050,7 +1050,7 @@
             pollUs <<= 1;
         } while (tryCounter-- > 0);
         if (tryCounter < 0) {
-            ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mId);
+            ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mPortId);
         }
         // Run again immediately
         return 0;
@@ -1174,7 +1174,7 @@
         timeout.tv_sec = ns / 1000000000LL;
         timeout.tv_nsec = ns % 1000000000LL;
         ALOGV("%s(%d): timeout %ld.%03d",
-                __func__, mId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
+                __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
         requested = &timeout;
     }
 
@@ -1187,17 +1187,17 @@
         status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
         LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
                 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
-                __func__, mId, err, audioBuffer.frameCount);
+                __func__, mPortId, err, audioBuffer.frameCount);
         requested = &ClientProxy::kNonBlocking;
         size_t avail = audioBuffer.frameCount + nonContig;
         ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
-                __func__, mId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
+                __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
         if (err != NO_ERROR) {
             if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
                 break;
             }
             ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
-                    __func__, mId, err);
+                    __func__, mPortId, err);
             return NS_NEVER;
         }
 
@@ -1220,7 +1220,7 @@
         // Sanity check on returned size
         if (ssize_t(readSize) < 0 || readSize > reqSize) {
             ALOGE("%s(%d):  EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
-                    __func__, mId, reqSize, ssize_t(readSize));
+                    __func__, mPortId, reqSize, ssize_t(readSize));
             return NS_NEVER;
         }
 
@@ -1280,7 +1280,7 @@
 
 status_t AudioRecord::restoreRecord_l(const char *from)
 {
-    ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mId, from);
+    ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mPortId, from);
     ++mSequence;
 
     const int INITIAL_RETRIES = 3;
@@ -1311,7 +1311,7 @@
     }
 
     if (result != NO_ERROR) {
-        ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
+        ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
         if (--retries > 0) {
             // leave time for an eventual race condition to clear before retrying
             usleep(500000);
@@ -1330,18 +1330,18 @@
 status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): adding NULL callback!", __func__, mId);
+        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() == callback.get()) {
-        ALOGW("%s(%d): adding same callback!", __func__, mId);
+        ALOGW("%s(%d): adding same callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     status_t status = NO_ERROR;
     if (mInput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
-            ALOGW("%s(%d): callback already present!", __func__, mId);
+            ALOGW("%s(%d): callback already present!", __func__, mPortId);
             AudioSystem::removeAudioDeviceCallback(this, mInput);
         }
         status = AudioSystem::addAudioDeviceCallback(this, mInput);
@@ -1354,12 +1354,12 @@
         const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): removing NULL callback!", __func__, mId);
+        ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() != callback.get()) {
-        ALOGW("%s(%d): removing different callback!", __func__, mId);
+        ALOGW("%s(%d): removing different callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     mDeviceCallback.clear();
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 78f3cae..3e91717 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -917,11 +917,11 @@
             config, flags, selectedDeviceId, portId);
 }
 
-status_t AudioSystem::startInput(audio_port_handle_t portId, bool *silenced)
+status_t AudioSystem::startInput(audio_port_handle_t portId)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
-    return aps->startInput(portId, silenced);
+    return aps->startInput(portId);
 }
 
 status_t AudioSystem::stopInput(audio_port_handle_t portId)
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 8607ee1..8f06ee7 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -30,9 +30,11 @@
 #include <utils/Log.h>
 #include <private/media/AudioTrackShared.h>
 #include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
 #include <media/AudioParameter.h>
 #include <media/AudioPolicyHelper.h>
 #include <media/AudioResamplerPublic.h>
+#include <media/AudioSystem.h>
 #include <media/MediaAnalyticsItem.h>
 #include <media/TypeConverter.h>
 
@@ -157,6 +159,15 @@
     return NO_ERROR;
 }
 
+// static
+bool AudioTrack::isDirectOutputSupported(const audio_config_base_t& config,
+                                         const audio_attributes_t& attributes) {
+    ALOGV("%s()", __FUNCTION__);
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return false;
+    return aps->isDirectOutputSupported(config, attributes);
+}
+
 // ---------------------------------------------------------------------------
 
 static std::string audioContentTypeString(audio_content_type_t value) {
@@ -344,7 +355,7 @@
         mSharedBuffer.clear();
         IPCThreadState::self()->flushCommands();
         ALOGV("%s(%d), releasing session id %d from %d on behalf of %d",
-                __func__, mId,
+                __func__, mPortId,
                 mSessionId, IPCThreadState::self()->getCallingPid(), mClientPid);
         AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
     }
@@ -377,7 +388,7 @@
     pid_t callingPid;
     pid_t myPid;
 
-    // Note mId is not valid until the track is created, so omit mId in ALOG for set.
+    // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
     ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
           __func__,
@@ -465,16 +476,7 @@
                 __func__,
                  mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
         mStreamType = AUDIO_STREAM_DEFAULT;
-        if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
-            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
-        }
-        if ((mAttributes.flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
-            flags = (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_FAST);
-        }
-        // check deep buffer after flags have been modified above
-        if (flags == AUDIO_OUTPUT_FLAG_NONE && (mAttributes.flags & AUDIO_FLAG_DEEP_BUFFER) != 0) {
-            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        }
+        audio_attributes_flags_to_audio_output_flags(mAttributes.flags, flags);
     }
 
     // these below should probably come from the audioFlinger too...
@@ -658,7 +660,7 @@
 status_t AudioTrack::start()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
         return INVALID_OPERATION;
@@ -699,7 +701,7 @@
             // It is possible since flush and stop are asynchronous that the server
             // is still active at this point.
             ALOGV("%s(%d): server read:%lld  cumulative flushed:%lld  client written:%lld",
-                    __func__, mId,
+                    __func__, mPortId,
                     (long long)(mFramesWrittenServerOffset
                             + mStartEts.mPosition[ExtendedTimestamp::LOCATION_SERVER]),
                     (long long)mStartEts.mFlushed,
@@ -760,7 +762,7 @@
         // Start our local VolumeHandler for restoration purposes.
         mVolumeHandler->setStarted();
     } else {
-        ALOGE("%s(%d): status %d", __func__, mId, status);
+        ALOGE("%s(%d): status %d", __func__, mPortId, status);
         mState = previousState;
         if (t != 0) {
             if (previousState != STATE_STOPPING) {
@@ -778,7 +780,7 @@
 void AudioTrack::stop()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
         return;
@@ -789,7 +791,7 @@
     } else {
         mState = STATE_STOPPED;
         ALOGD_IF(mSharedBuffer == nullptr,
-                "%s(%d): called with %u frames delivered", __func__, mId, mReleased.value());
+                "%s(%d): called with %u frames delivered", __func__, mPortId, mReleased.value());
         mReleased = 0;
     }
 
@@ -830,7 +832,7 @@
 void AudioTrack::flush()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mSharedBuffer != 0) {
         return;
@@ -863,7 +865,7 @@
 void AudioTrack::pause()
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s", __func__, mId, stateToString(mState));
+    ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
 
     if (mState == STATE_ACTIVE) {
         mState = STATE_PAUSED;
@@ -891,7 +893,7 @@
             uint32_t halFrames;
             AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition);
             ALOGV("%s(%d): for offload, cache current position %u",
-                    __func__, mId, mPausedPosition);
+                    __func__, mPortId, mPausedPosition);
         }
     }
 }
@@ -945,7 +947,7 @@
 status_t AudioTrack::setSampleRate(uint32_t rate)
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): prior state:%s rate:%u", __func__, mId, stateToString(mState), rate);
+    ALOGV("%s(%d): prior state:%s rate:%u", __func__, mPortId, stateToString(mState), rate);
 
     if (rate == mSampleRate) {
         return NO_ERROR;
@@ -1013,7 +1015,7 @@
     }
 
     ALOGV("%s(%d): mSampleRate:%u  mSpeed:%f  mPitch:%f",
-            __func__, mId, mSampleRate, playbackRate.mSpeed, playbackRate.mPitch);
+            __func__, mPortId, mSampleRate, playbackRate.mSpeed, playbackRate.mPitch);
     // pitch is emulated by adjusting speed and sampleRate
     const uint32_t effectiveRate = adjustSampleRate(mSampleRate, playbackRate.mPitch);
     const float effectiveSpeed = adjustSpeed(playbackRate.mSpeed, playbackRate.mPitch);
@@ -1023,17 +1025,17 @@
     playbackRateTemp.mPitch = effectivePitch;
 
     ALOGV("%s(%d) (effective) mSampleRate:%u  mSpeed:%f  mPitch:%f",
-            __func__, mId, effectiveRate, effectiveSpeed, effectivePitch);
+            __func__, mPortId, effectiveRate, effectiveSpeed, effectivePitch);
 
     if (!isAudioPlaybackRateValid(playbackRateTemp)) {
         ALOGW("%s(%d) (%f, %f) failed (effective rate out of bounds)",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
     // Check if the buffer size is compatible.
     if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) {
         ALOGW("%s(%d) (%f, %f) failed (buffer size)",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
 
@@ -1041,13 +1043,13 @@
     if ((uint64_t)effectiveRate > (uint64_t)mSampleRate *
             (uint64_t)AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
         ALOGW("%s(%d) (%f, %f) failed. Resample rate exceeds max accepted value",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
 
     if ((uint64_t)effectiveRate * (uint64_t)AUDIO_RESAMPLER_UP_RATIO_MAX < (uint64_t)mSampleRate) {
         ALOGW("%s(%d) (%f, %f) failed. Resample rate below min accepted value",
-                __func__, mId, playbackRate.mSpeed, playbackRate.mPitch);
+                __func__, mPortId, playbackRate.mSpeed, playbackRate.mPitch);
         return BAD_VALUE;
     }
     mPlaybackRate = playbackRate;
@@ -1249,7 +1251,7 @@
 
         if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
             ALOGV("%s(%d): called in paused state, return cached position %u",
-                __func__, mId, mPausedPosition);
+                __func__, mPortId, mPausedPosition);
             *position = mPausedPosition;
             return NO_ERROR;
         }
@@ -1395,7 +1397,7 @@
 {
     status_t status = AudioSystem::getLatency(mOutput, &mAfLatency);
     if (status != NO_ERROR) {
-        ALOGW("%s(%d): getLatency(%d) failed status %d", __func__, mId, mOutput, status);
+        ALOGW("%s(%d): getLatency(%d) failed status %d", __func__, mPortId, mOutput, status);
     } else {
         // FIXME don't believe this lie
         mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
@@ -1425,7 +1427,7 @@
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
         ALOGE("%s(%d): Could not get audioflinger",
-                __func__, mId);
+                __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -1451,7 +1453,7 @@
         if (!fastAllowed) {
             ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by client,"
                   " not shared buffer and transfer = %s",
-                  __func__, mId,
+                  __func__, mPortId,
                   convertTransferToText(mTransfer));
             mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
         }
@@ -1501,7 +1503,7 @@
 
     if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
         ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
-                __func__, mId, status, output.outputId);
+                __func__, mPortId, status, output.outputId);
         if (status == NO_ERROR) {
             status = NO_INIT;
         }
@@ -1522,7 +1524,7 @@
     mAfFrameCount = output.afFrameCount;
     mAfSampleRate = output.afSampleRate;
     mAfLatency = output.afLatencyMs;
-    mId = output.trackId;
+    mPortId = output.portId;
 
     mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
 
@@ -1532,13 +1534,13 @@
     // FIXME compare to AudioRecord
     sp<IMemory> iMem = track->getCblk();
     if (iMem == 0) {
-        ALOGE("%s(%d): Could not get control block", __func__, mId);
+        ALOGE("%s(%d): Could not get control block", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
     void *iMemPointer = iMem->pointer();
     if (iMemPointer == NULL) {
-        ALOGE("%s(%d): Could not get control block pointer", __func__, mId);
+        ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
         status = NO_INIT;
         goto exit;
     }
@@ -1558,13 +1560,13 @@
     if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
         if (output.flags & AUDIO_OUTPUT_FLAG_FAST) {
             ALOGI("%s(%d): AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu",
-                  __func__, mId, mReqFrameCount, mFrameCount);
+                  __func__, mPortId, mReqFrameCount, mFrameCount);
             if (!mThreadCanCallJava) {
                 mAwaitBoost = true;
             }
         } else {
             ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu",
-                  __func__, mId, mReqFrameCount, mFrameCount);
+                  __func__, mPortId, mReqFrameCount, mFrameCount);
         }
     }
     mFlags = output.flags;
@@ -1592,7 +1594,7 @@
     } else {
         buffers = mSharedBuffer->pointer();
         if (buffers == NULL) {
-            ALOGE("%s(%d): Could not get buffer pointer", __func__, mId);
+            ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
             status = NO_INIT;
             goto exit;
         }
@@ -1681,7 +1683,7 @@
         timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
-        ALOGE("%s(%d): invalid waitCount %d", __func__, mId, waitCount);
+        ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
         requested = NULL;
     }
     return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
@@ -1792,7 +1794,7 @@
     int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
     if ((mState == STATE_ACTIVE) && (flags & CBLK_DISABLED)) {
         ALOGW("%s(%d): releaseBuffer() track %p disabled due to previous underrun, restarting",
-                __func__, mId, this);
+                __func__, mPortId, this);
         // FIXME ignoring status
         mAudioTrack->start();
     }
@@ -1820,7 +1822,7 @@
         // Sanity-check: user is most-likely passing an error code, and it would
         // make the return value ambiguous (actualSize vs error).
         ALOGE("%s(%d): AudioTrack::write(buffer=%p, size=%zu (%zd)",
-                __func__, mId, buffer, userSize, userSize);
+                __func__, mPortId, buffer, userSize, userSize);
         return BAD_VALUE;
     }
 
@@ -1893,7 +1895,7 @@
         } while (tryCounter-- > 0);
         if (tryCounter < 0) {
             ALOGE("%s(%d): did not receive expected priority boost on time",
-                    __func__, mId);
+                    __func__, mPortId);
         }
         // Run again immediately
         return 0;
@@ -2135,7 +2137,7 @@
         timeout.tv_sec = ns / 1000000000LL;
         timeout.tv_nsec = ns % 1000000000LL;
         ALOGV("%s(%d): timeout %ld.%03d",
-                __func__, mId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
+                __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
         requested = &timeout;
     }
 
@@ -2148,11 +2150,11 @@
         status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
         LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
                 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
-                 __func__, mId, err, audioBuffer.frameCount);
+                 __func__, mPortId, err, audioBuffer.frameCount);
         requested = &ClientProxy::kNonBlocking;
         size_t avail = audioBuffer.frameCount + nonContig;
         ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
-                __func__, mId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
+                __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
         if (err != NO_ERROR) {
             if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR ||
                     (isOffloaded() && (err == DEAD_OBJECT))) {
@@ -2160,7 +2162,7 @@
                 return 1000000;
             }
             ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
-                    __func__, mId, err);
+                    __func__, mPortId, err);
             return NS_NEVER;
         }
 
@@ -2192,7 +2194,7 @@
         // Sanity check on returned size
         if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
             ALOGE("%s(%d): EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
-                    __func__, mId, reqSize, ssize_t(writtenSize));
+                    __func__, mPortId, reqSize, ssize_t(writtenSize));
             return NS_NEVER;
         }
 
@@ -2296,7 +2298,7 @@
 status_t AudioTrack::restoreTrack_l(const char *from)
 {
     ALOGW("%s(%d): dead IAudioTrack, %s, creating a new one from %s()",
-            __func__, mId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
+            __func__, mPortId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
     ++mSequence;
 
     // refresh the audio configuration cache in this process to make sure we get new
@@ -2354,7 +2356,7 @@
             } else {
                 mStaticProxy->setBufferPosition(bufferPosition);
                 if (bufferPosition == mFrameCount) {
-                    ALOGD("%s(%d): restoring track at end of static buffer", __func__, mId);
+                    ALOGD("%s(%d): restoring track at end of static buffer", __func__, mPortId);
                 }
             }
         }
@@ -2384,7 +2386,7 @@
         mFramesWrittenAtRestore = mFramesWrittenServerOffset;
     }
     if (result != NO_ERROR) {
-        ALOGW("%s(%d): failed status %d, retries %d", __func__, mId, result, retries);
+        ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
         if (--retries > 0) {
             // leave time for an eventual race condition to clear before retrying
             usleep(500000);
@@ -2414,7 +2416,7 @@
     //      in which case the use of uint32_t for these counters has bigger issues.
     ALOGE_IF(delta < 0,
             "%s(%d): detected illegal retrograde motion by the server: mServer advanced by %d",
-            __func__, mId, delta);
+            __func__, mPortId, delta);
     mServer = newServer;
     if (delta > 0) { // avoid retrograde
         mPosition += delta;
@@ -2437,7 +2439,7 @@
             "%s(%d): denied "
             "mAfLatency:%u  mAfFrameCount:%zu  mAfSampleRate:%u  sampleRate:%u  speed:%f "
             "mFrameCount:%zu < minFrameCount:%zu",
-            __func__, mId,
+            __func__, mPortId,
             mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed,
             mFrameCount, minFrameCount);
     return allowed;
@@ -2452,8 +2454,13 @@
 status_t AudioTrack::selectPresentation(int presentationId, int programId)
 {
     AutoMutex lock(mLock);
-    ALOGV("%s(%d): PresentationId:%d ProgramId:%d", __func__, mId, presentationId, programId);
-    return mAudioTrack->selectPresentation(presentationId, programId);
+    AudioParameter param = AudioParameter();
+    param.addInt(String8(AudioParameter::keyPresentationId), presentationId);
+    param.addInt(String8(AudioParameter::keyProgramId), programId);
+    ALOGV("%s(%d): PresentationId/ProgramId[%s]",
+            __func__, mPortId, param.toString().string());
+
+    return mAudioTrack->setParameters(param.toString());
 }
 
 VolumeShaper::Status AudioTrack::applyVolumeShaper(
@@ -2478,7 +2485,7 @@
     } else {
         // warn only if not an expected restore failure.
         ALOGW_IF(!((isOffloadedOrDirect_l() || mDoNotReconnect) && status == DEAD_OBJECT),
-                "%s(%d): applyVolumeShaper failed: %d", __func__, mId, status);
+                "%s(%d): applyVolumeShaper failed: %d", __func__, mPortId, status);
     }
     return status;
 }
@@ -2520,7 +2527,7 @@
     }
     status_t status = mProxy->getTimestamp(timestamp);
     LOG_ALWAYS_FATAL_IF(status != OK, "%s(%d): status %d not allowed from proxy getTimestamp",
-            __func__, mId, status);
+            __func__, mPortId, status);
     bool found = false;
     timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesWritten;
     timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
@@ -2564,7 +2571,7 @@
         break; // offloaded tracks handled below
     default:
         LOG_ALWAYS_FATAL("%s(%d): Invalid mState in getTimestamp(): %d",
-               __func__, mId, mState);
+               __func__, mPortId, mState);
         break;
     }
 
@@ -2599,7 +2606,7 @@
                 if (location == ExtendedTimestamp::LOCATION_SERVER) {
                     ALOGW_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_KERNEL,
                             "%s(%d): location moved from kernel to server",
-                            __func__, mId);
+                            __func__, mPortId);
                     // check that the last kernel OK time info exists and the positions
                     // are valid (if they predate the current track, the positions may
                     // be zero or negative).
@@ -2615,7 +2622,7 @@
                             (ets.mPosition[ExtendedTimestamp::LOCATION_SERVER_LASTKERNELOK]
                             - ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL_LASTKERNELOK]);
                     ALOGV("%s(%d): frame adjustment:%lld  timestamp:%s",
-                            __func__, mId, (long long)frames, ets.toString().c_str());
+                            __func__, mPortId, (long long)frames, ets.toString().c_str());
                     if (frames >= ets.mPosition[location]) {
                         timestamp.mPosition = 0;
                     } else {
@@ -2624,7 +2631,7 @@
                 } else if (location == ExtendedTimestamp::LOCATION_KERNEL) {
                     ALOGV_IF(mPreviousLocation == ExtendedTimestamp::LOCATION_SERVER,
                             "%s(%d): location moved from server to kernel",
-                            __func__, mId);
+                            __func__, mPortId);
                 }
 
                 // We update the timestamp time even when paused.
@@ -2648,7 +2655,7 @@
                 mPreviousLocation = location;
             } else {
                 // right after AudioTrack is started, one may not find a timestamp
-                ALOGV("%s(%d): getBestTimestamp did not find timestamp", __func__, mId);
+                ALOGV("%s(%d): getBestTimestamp did not find timestamp", __func__, mPortId);
             }
         }
         if (status == INVALID_OPERATION) {
@@ -2659,7 +2666,7 @@
             // "zero" for NuPlayer).  We don't convert for track restoration as position
             // does not reset.
             ALOGV("%s(%d): timestamp server offset:%lld restore frames:%lld",
-                    __func__, mId,
+                    __func__, mPortId,
                     (long long)mFramesWrittenServerOffset, (long long)mFramesWrittenAtRestore);
             if (mFramesWrittenServerOffset != mFramesWrittenAtRestore) {
                 status = WOULD_BLOCK;
@@ -2667,7 +2674,7 @@
         }
     }
     if (status != NO_ERROR) {
-        ALOGV_IF(status != WOULD_BLOCK, "%s(%d): getTimestamp error:%#x", __func__, mId, status);
+        ALOGV_IF(status != WOULD_BLOCK, "%s(%d): getTimestamp error:%#x", __func__, mPortId, status);
         return status;
     }
     if (isOffloadedOrDirect_l()) {
@@ -2708,7 +2715,7 @@
                     ALOGW_IF(!mTimestampStartupGlitchReported,
                             "%s(%d): startup glitch detected"
                             " deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)",
-                            __func__, mId,
+                            __func__, mPortId,
                             (long long)deltaTimeUs, (long long)deltaPositionByUs,
                             timestamp.mPosition);
                     mTimestampStartupGlitchReported = true;
@@ -2778,7 +2785,7 @@
             if (currentTimeNanos < limitNs) {
                 ALOGD("%s(%d): correcting timestamp time for pause, "
                         "currentTimeNanos: %lld < limitNs: %lld < mStartNs: %lld",
-                        __func__, mId,
+                        __func__, mPortId,
                         (long long)currentTimeNanos, (long long)limitNs, (long long)mStartNs);
                 timestamp.mTime = convertNsToTimespec(limitNs);
                 currentTimeNanos = limitNs;
@@ -2787,7 +2794,7 @@
             // retrograde check
             if (currentTimeNanos < previousTimeNanos) {
                 ALOGW("%s(%d): retrograde timestamp time corrected, %lld < %lld",
-                        __func__, mId,
+                        __func__, mPortId,
                         (long long)currentTimeNanos, (long long)previousTimeNanos);
                 timestamp.mTime = mPreviousTimestamp.mTime;
                 // currentTimeNanos not used below.
@@ -2801,7 +2808,7 @@
                 // Only report once per position instead of spamming the log.
                 if (!mRetrogradeMotionReported) {
                     ALOGW("%s(%d): retrograde timestamp position corrected, %d = %u - %u",
-                            __func__, mId,
+                            __func__, mPortId,
                             deltaPosition,
                             timestamp.mPosition,
                             mPreviousTimestamp.mPosition);
@@ -2822,7 +2829,7 @@
                 const int64_t computedSampleRate =
                         deltaPosition * (long long)NANOS_PER_SECOND / deltaTime;
                 ALOGD("%s(%d): computedSampleRate:%u  sampleRate:%u",
-                        __func__, mId,
+                        __func__, mPortId,
                         (unsigned)computedSampleRate, mSampleRate);
             }
 #endif
@@ -2869,7 +2876,7 @@
 
     result.append(" AudioTrack::dump\n");
     result.appendFormat("  id(%d) status(%d), state(%d), session Id(%d), flags(%#x)\n",
-                        mId, mStatus, mState, mSessionId, mFlags);
+                        mPortId, mStatus, mState, mSessionId, mFlags);
     result.appendFormat("  stream type(%d), left - right volume(%f, %f)\n",
                         (mStreamType == AUDIO_STREAM_DEFAULT) ?
                                 audio_attributes_to_stream_type(&mAttributes) : mStreamType,
@@ -2911,18 +2918,18 @@
 status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): adding NULL callback!", __func__, mId);
+        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() == callback.get()) {
-        ALOGW("%s(%d): adding same callback!", __func__, mId);
+        ALOGW("%s(%d): adding same callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     status_t status = NO_ERROR;
     if (mOutput != AUDIO_IO_HANDLE_NONE) {
         if (mDeviceCallback != 0) {
-            ALOGW("%s(%d): callback already present!", __func__, mId);
+            ALOGW("%s(%d): callback already present!", __func__, mPortId);
             AudioSystem::removeAudioDeviceCallback(this, mOutput);
         }
         status = AudioSystem::addAudioDeviceCallback(this, mOutput);
@@ -2935,12 +2942,12 @@
         const sp<AudioSystem::AudioDeviceCallback>& callback)
 {
     if (callback == 0) {
-        ALOGW("%s(%d): removing NULL callback!", __func__, mId);
+        ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
     if (mDeviceCallback.unsafe_get() != callback.get()) {
-        ALOGW("%s(%d): removing different callback!", __func__, mId);
+        ALOGW("%s(%d): removing different callback!", __func__, mPortId);
         return INVALID_OPERATION;
     }
     mDeviceCallback.clear();
@@ -3046,7 +3053,7 @@
     case STATE_FLUSHED:
         return false;  // we're not active
     default:
-        LOG_ALWAYS_FATAL("%s(%d): Invalid mState in hasStarted(): %d", __func__, mId, mState);
+        LOG_ALWAYS_FATAL("%s(%d): Invalid mState in hasStarted(): %d", __func__, mPortId, mState);
         break;
     }
 
@@ -3063,7 +3070,7 @@
             wait = (ts.mPosition == 0 || ts.mPosition == mStartTs.mPosition);
         }
         ALOGV("%s(%d): hasStarted wait:%d  ts:%u  start position:%lld",
-                __func__, mId,
+                __func__, mPortId,
                 (int)wait,
                 ts.mPosition,
                 (long long)mStartTs.mPosition);
@@ -3085,7 +3092,7 @@
             }
         }
         ALOGV("%s(%d): hasStarted wait:%d  ets:%lld  start position:%lld",
-                __func__, mId,
+                __func__, mPortId,
                 (int)wait,
                 (long long)ets.mPosition[location],
                 (long long)mStartEts.mPosition[location]);
@@ -3161,7 +3168,7 @@
         FALLTHROUGH_INTENDED;
     default:
         LOG_ALWAYS_FATAL_IF(ns < 0, "%s(%d): processAudioBuffer() returned %lld",
-                __func__, mReceiver.mId, (long long)ns);
+                __func__, mReceiver.mPortId, (long long)ns);
         pauseInternal(ns);
         return true;
     }
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 555ac87..0ce8b16 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -62,6 +62,7 @@
     SET_EFFECT_ENABLED,
     IS_STREAM_ACTIVE_REMOTELY,
     IS_OFFLOAD_SUPPORTED,
+    IS_DIRECT_OUTPUT_SUPPORTED,
     LIST_AUDIO_PORTS,
     GET_AUDIO_PORT,
     CREATE_AUDIO_PATCH,
@@ -330,16 +331,13 @@
         return NO_ERROR;
     }
 
-    virtual status_t startInput(audio_port_handle_t portId,
-                                bool *silenced)
+    virtual status_t startInput(audio_port_handle_t portId)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(portId);
-        data.writeInt32(*silenced ? 1 : 0);
         remote()->transact(START_INPUT, data, &reply);
         status_t status = static_cast <status_t> (reply.readInt32());
-        *silenced = reply.readInt32() == 1;
         return status;
     }
 
@@ -527,6 +525,16 @@
         return reply.readInt32();
     }
 
+    virtual bool isDirectOutputSupported(const audio_config_base_t& config,
+                                         const audio_attributes_t& attributes) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&config, sizeof(audio_config_base_t));
+        data.write(&attributes, sizeof(audio_attributes_t));
+        status_t status = remote()->transact(IS_DIRECT_OUTPUT_SUPPORTED, data, &reply);
+        return status == NO_ERROR ? static_cast<bool>(reply.readInt32()) : false;
+    }
+
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
                                     unsigned int *num_ports,
@@ -1231,10 +1239,8 @@
         case START_INPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_port_handle_t portId = static_cast <audio_port_handle_t>(data.readInt32());
-            bool silenced = data.readInt32() == 1;
-            status_t status = startInput(portId, &silenced);
+            status_t status = startInput(portId);
             reply->writeInt32(static_cast <uint32_t>(status));
-            reply->writeInt32(silenced ? 1 : 0);
             return NO_ERROR;
         } break;
 
@@ -1405,6 +1411,18 @@
             return NO_ERROR;
         }
 
+        case IS_DIRECT_OUTPUT_SUPPORTED: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_config_base_t config = {};
+            audio_attributes_t attributes = {};
+            status_t status = data.read(&config, sizeof(audio_config_base_t));
+            if (status != NO_ERROR) return status;
+            status = data.read(&attributes, sizeof(audio_attributes_t));
+            if (status != NO_ERROR) return status;
+            reply->writeInt32(isDirectOutputSupported(config, attributes));
+            return NO_ERROR;
+        }
+
         case LIST_AUDIO_PORTS: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_port_role_t role = (audio_port_role_t)data.readInt32();
diff --git a/media/libaudioclient/include/media/AudioPolicyHelper.h b/media/libaudioclient/include/media/AudioPolicyHelper.h
index 49432b7..46de6b3 100644
--- a/media/libaudioclient/include/media/AudioPolicyHelper.h
+++ b/media/libaudioclient/include/media/AudioPolicyHelper.h
@@ -123,4 +123,21 @@
     }
 }
 
+// Convert flags sent from Java AudioAttributes.getFlags() method to audio_output_flags_t
+static inline
+void audio_attributes_flags_to_audio_output_flags(const audio_flags_mask_t audioAttributeFlags,
+            audio_output_flags_t &flags) {
+    if ((audioAttributeFlags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+        flags = static_cast<audio_output_flags_t>(flags |
+            AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_DIRECT);
+    }
+    if ((audioAttributeFlags & AUDIO_FLAG_LOW_LATENCY) != 0) {
+        flags = static_cast<audio_output_flags_t>(flags | AUDIO_OUTPUT_FLAG_FAST);
+    }
+    // check deep buffer after flags have been modified above
+    if (flags == AUDIO_OUTPUT_FLAG_NONE && (audioAttributeFlags & AUDIO_FLAG_DEEP_BUFFER) != 0) {
+        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+    }
+}
+
 #endif //AUDIO_POLICY_HELPER_H_
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index c226557..35a7e05 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -534,9 +534,15 @@
      */
             status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
 
-    /*
-     * Dumps the state of an audio record.
-     */
+     /* Get the unique port ID assigned to this AudioRecord instance by audio policy manager.
+      * The ID is unique across all audioserver clients and can change during the life cycle
+      * of a given AudioRecord instance if the connection to audioserver is restored.
+      */
+            audio_port_handle_t getPortId() const { return mPortId; };
+
+     /*
+      * Dumps the state of an audio record.
+      */
             status_t    dump(int fd, const Vector<String16>& args) const;
 
 private:
@@ -654,7 +660,7 @@
     audio_input_flags_t     mOrigFlags;             // as specified in constructor or set(), const
 
     audio_session_t         mSessionId;
-    int                     mId;                    // Id from AudioFlinger
+    audio_port_handle_t     mPortId;                    // Id from Audio Policy Manager
     transfer_type           mTransfer;
 
     // Next 5 fields may be changed if IAudioRecord is re-created, but always != 0
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index a04b494..74156ca 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -241,8 +241,7 @@
                                     audio_port_handle_t *selectedDeviceId,
                                     audio_port_handle_t *portId);
 
-    static status_t startInput(audio_port_handle_t portId,
-                               bool *silenced);
+    static status_t startInput(audio_port_handle_t portId);
     static status_t stopInput(audio_port_handle_t portId);
     static void releaseInput(audio_port_handle_t portId);
     static status_t initStreamVolume(audio_stream_type_t stream,
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 4b84fd1..7fdf7cc 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -147,6 +147,12 @@
                                      audio_stream_type_t streamType,
                                      uint32_t sampleRate);
 
+    /* Check if direct playback is possible for the given audio configuration and attributes.
+     * Return true if output is possible for the given parameters. Otherwise returns false.
+     */
+    static bool isDirectOutputSupported(const audio_config_base_t& config,
+                                        const audio_attributes_t& attributes);
+
     /* How data is transferred to AudioTrack
      */
     enum transfer_type {
@@ -912,7 +918,14 @@
                 AutoMutex lock(mLock);
                 return mState == STATE_ACTIVE || mState == STATE_STOPPING;
             }
-protected:
+
+    /* Get the unique port ID assigned to this AudioTrack instance by audio policy manager.
+     * The ID is unique across all audioserver clients and can change during the life cycle
+     * of a given AudioTrack instance if the connection to audioserver is restored.
+     */
+            audio_port_handle_t getPortId() const { return mPortId; };
+
+ protected:
     /* copying audio tracks is not allowed */
                         AudioTrack(const AudioTrack& other);
             AudioTrack& operator = (const AudioTrack& other);
@@ -1166,7 +1179,7 @@
 
     audio_session_t         mSessionId;
     int                     mAuxEffectId;
-    int                     mId;                    // Id from AudioFlinger.
+    audio_port_handle_t     mPortId;                    // Id from Audio Policy Manager
 
     mutable Mutex           mLock;
 
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 52cc860..a34b207 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -146,7 +146,7 @@
             afSampleRate = parcel->readInt64();
             afLatencyMs = parcel->readInt32();
             (void)parcel->read(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->readInt32(&trackId);
+            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -164,7 +164,7 @@
             (void)parcel->writeInt64(afSampleRate);
             (void)parcel->writeInt32(afLatencyMs);
             (void)parcel->write(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->writeInt32(trackId);
+            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -181,7 +181,7 @@
         uint32_t afSampleRate;
         uint32_t afLatencyMs;
         audio_io_handle_t outputId;
-        int32_t trackId;
+        audio_port_handle_t portId;
     };
 
     /* CreateRecordInput contains all input arguments sent by AudioRecord to AudioFlinger
@@ -274,7 +274,7 @@
                     return BAD_VALUE;
                 }
             }
-            (void)parcel->readInt32(&trackId);
+            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
             return NO_ERROR;
         }
 
@@ -301,7 +301,7 @@
             } else {
                 (void)parcel->writeInt32(0);
             }
-            (void)parcel->writeInt32(trackId);
+            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
 
             return NO_ERROR;
         }
@@ -318,7 +318,7 @@
         audio_io_handle_t inputId;
         sp<IMemory> cblk;
         sp<IMemory> buffers;
-        int32_t trackId;
+        audio_port_handle_t portId;
     };
 
     // invariant on exit for all APIs that return an sp<>:
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index b74d25b..61f3b27 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -78,8 +78,7 @@
                               audio_input_flags_t flags,
                               audio_port_handle_t *selectedDeviceId,
                               audio_port_handle_t *portId) = 0;
-    virtual status_t startInput(audio_port_handle_t portId,
-                                bool *silenced) = 0;
+    virtual status_t startInput(audio_port_handle_t portId) = 0;
     virtual status_t stopInput(audio_port_handle_t portId) = 0;
     virtual void releaseInput(audio_port_handle_t portId) = 0;
     virtual status_t initStreamVolume(audio_stream_type_t stream,
@@ -126,6 +125,10 @@
     // bit rate, duration, video and streaming or offload property is enabled
     virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0;
 
+    // Check if direct playback is possible for given format, sample rate, channel mask and flags.
+    virtual bool isDirectOutputSupported(const audio_config_base_t& config,
+                                         const audio_attributes_t& attributes) = 0;
+
     /* List available audio ports and their attributes */
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 2d9e1cb..e06a1aa 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -63,7 +63,8 @@
 
 CopyBufferProvider::~CopyBufferProvider()
 {
-    ALOGV("~CopyBufferProvider(%p)", this);
+    ALOGV("%s(%p) %zu %p %p",
+           __func__, this, mBuffer.frameCount, mTrackBufferProvider, mLocalBufferData);
     if (mBuffer.frameCount != 0) {
         mTrackBufferProvider->releaseBuffer(&mBuffer);
     }
@@ -133,6 +134,16 @@
     mConsumed = 0;
 }
 
+void CopyBufferProvider::setBufferProvider(AudioBufferProvider *p) {
+    ALOGV("%s(%p): mTrackBufferProvider:%p  mBuffer.frameCount:%zu",
+            __func__, p, mTrackBufferProvider, mBuffer.frameCount);
+    if (mTrackBufferProvider == p) {
+        return;
+    }
+    mBuffer.frameCount = 0;
+    PassthruBufferProvider::setBufferProvider(p);
+}
+
 DownmixerBufferProvider::DownmixerBufferProvider(
         audio_channel_mask_t inputChannelMask,
         audio_channel_mask_t outputChannelMask, audio_format_t format,
@@ -528,6 +539,16 @@
     mRemaining = 0;
 }
 
+void TimestretchBufferProvider::setBufferProvider(AudioBufferProvider *p) {
+    ALOGV("%s(%p): mTrackBufferProvider:%p  mBuffer.frameCount:%zu",
+            __func__, p, mTrackBufferProvider, mBuffer.frameCount);
+    if (mTrackBufferProvider == p) {
+        return;
+    }
+    mBuffer.frameCount = 0;
+    PassthruBufferProvider::setBufferProvider(p);
+}
+
 status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
 {
     mPlaybackRate = playbackRate;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 3d9e62e..6002e95 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -113,9 +113,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -144,9 +141,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -267,9 +261,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -331,8 +322,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libmedia/NdkMediaFormatPriv.cpp b/media/libmedia/NdkMediaFormatPriv.cpp
index 3c84d6a..3a9fb8b 100644
--- a/media/libmedia/NdkMediaFormatPriv.cpp
+++ b/media/libmedia/NdkMediaFormatPriv.cpp
@@ -19,27 +19,22 @@
 
 #include <inttypes.h>
 
-//#include <ndk/include/media/NdkMediaFormat.h>
-
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
 #include <media/NdkMediaFormatPriv.h>
-#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
-//#include <android_runtime/AndroidRuntime.h>
-//#include <android_util_Binder.h>
 
 #include <jni.h>
 
 using namespace android;
 
-extern "C" {
+namespace android {
 
 // private functions for conversion to/from AMessage
-AMediaFormat* AMediaFormat_fromMsg(const void* data) {
+AMediaFormat* AMediaFormat_fromMsg(sp<AMessage> *data) {
     ALOGV("private ctor");
     AMediaFormat* mData = new AMediaFormat();
-    mData->mFormat = *((sp<AMessage>*)data);
+    mData->mFormat = *data;
     if (mData->mFormat == NULL) {
         ALOGW("got NULL format");
         mData->mFormat = new AMessage;
@@ -47,10 +42,10 @@
     return mData;
 }
 
-void AMediaFormat_getFormat(const AMediaFormat* mData, void* dest) {
-    *((sp<AMessage>*)dest) = mData->mFormat;
+void AMediaFormat_getFormat(const AMediaFormat* mData, sp<AMessage> *dest) {
+    *dest = mData->mFormat;
 }
 
-} // extern "C"
+} // namespace android
 
 
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libmedia/include/media/BufferProviders.h
index d6a9cfb..2f1a91c 100644
--- a/media/libmedia/include/media/BufferProviders.h
+++ b/media/libmedia/include/media/BufferProviders.h
@@ -78,6 +78,7 @@
 
     // Overrides PassthruBufferProvider
     virtual void reset();
+    void setBufferProvider(AudioBufferProvider *p) override;
 
     // this function should be supplied by the derived class.  It converts
     // #frames in the *src pointer to the *dst pointer.  It is public because
@@ -186,6 +187,7 @@
 
     // Overrides PassthruBufferProvider
     virtual void reset();
+    void setBufferProvider(AudioBufferProvider *p) override;
 
     virtual status_t setPlaybackRate(const AudioPlaybackRate &playbackRate);
 
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 0871d60..6f2b35f 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -48,8 +48,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libmediaextractor/MediaBufferGroup.cpp b/media/libmediaextractor/MediaBufferGroup.cpp
index 62b83cc..4e6beca 100644
--- a/media/libmediaextractor/MediaBufferGroup.cpp
+++ b/media/libmediaextractor/MediaBufferGroup.cpp
@@ -44,12 +44,16 @@
 };
 
 MediaBufferGroup::MediaBufferGroup(size_t growthLimit)
-    : mInternal(new InternalData()) {
+    : mWrapper(nullptr), mInternal(new InternalData()) {
     mInternal->mGrowthLimit = growthLimit;
 }
 
 MediaBufferGroup::MediaBufferGroup(size_t buffers, size_t buffer_size, size_t growthLimit)
-    : mInternal(new InternalData()) {
+    : mWrapper(nullptr), mInternal(new InternalData()) {
+    init(buffers, buffer_size, growthLimit);
+}
+
+void MediaBufferGroup::init(size_t buffers, size_t buffer_size, size_t growthLimit) {
     mInternal->mGrowthLimit = growthLimit;
 
     if (mInternal->mGrowthLimit > 0 && buffers > mInternal->mGrowthLimit) {
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index cb96ff5..1f7a473 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -22,7 +22,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/DataSourceBase.h>
 #include <media/IDataSource.h>
-#include <media/MediaExtractorPluginHelper.h>
+#include <media/MediaExtractorPluginApi.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
index 6c8d94a..d67ddbd 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
@@ -18,6 +18,10 @@
 
 #define MEDIA_BUFFER_BASE_H_
 
+#include <media/MediaExtractorPluginApi.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/NdkMediaFormatPriv.h>
+
 namespace android {
 
 class MediaBufferBase;
@@ -77,6 +81,48 @@
     virtual int remoteRefcount() const = 0;
 
     virtual ~MediaBufferBase() {};
+
+    CMediaBufferV3 *wrap() {
+        if (mWrapper) {
+            return mWrapper;
+        }
+        mWrapper = new CMediaBufferV3;
+        mWrapper->handle = this;
+
+        mWrapper->release = [](void *handle) -> void {
+            ((MediaBufferBase*)handle)->release();
+        };
+
+        mWrapper->data = [](void *handle) -> void * {
+            return ((MediaBufferBase*)handle)->data();
+        };
+
+        mWrapper->size = [](void *handle) -> size_t {
+            return ((MediaBufferBase*)handle)->size();
+        };
+
+        mWrapper->set_range = [](void *handle, size_t offset, size_t length) -> void {
+            return ((MediaBufferBase*)handle)->set_range(offset, length);
+        };
+
+        mWrapper->meta_data = [](void *handle) -> AMediaFormat* {
+            if (((MediaBufferBase*)handle)->mFormat == nullptr) {
+                sp<AMessage> msg = new AMessage();
+                ((MediaBufferBase*)handle)->mFormat = AMediaFormat_fromMsg(&msg);
+            }
+            return ((MediaBufferBase*)handle)->mFormat;
+        };
+
+        return mWrapper;
+    }
+protected:
+    MediaBufferBase() {
+        mWrapper = nullptr;
+        mFormat = nullptr;
+    }
+private:
+    CMediaBufferV3 *mWrapper;
+    AMediaFormat *mFormat;
 };
 
 }  // namespace android
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h b/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
index 75d5df7..dc04556 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
@@ -20,6 +20,8 @@
 
 #include <list>
 
+#include <media/MediaExtractorPluginApi.h>
+#include <media/NdkMediaErrorPriv.h>
 #include <media/stagefright/MediaBufferBase.h>
 #include <utils/Errors.h>
 #include <utils/threads.h>
@@ -57,12 +59,54 @@
     // If buffer is nullptr, have acquire_buffer() check for remote release.
     virtual void signalBufferReturned(MediaBufferBase *buffer);
 
+    CMediaBufferGroupV3 *wrap() {
+        if (mWrapper) {
+            return mWrapper;
+        }
+
+        mWrapper = new CMediaBufferGroupV3;
+        mWrapper->handle = this;
+
+        mWrapper->add_buffer = [](void *handle, size_t size) -> void {
+            MediaBufferBase *buf = MediaBufferBase::Create(size);
+            ((MediaBufferGroup*)handle)->add_buffer(buf);
+        };
+
+        mWrapper->init = [](void *handle,
+                size_t buffers, size_t buffer_size, size_t growthLimit) -> bool {
+            ((MediaBufferGroup*)handle)->init(buffers, buffer_size, growthLimit);
+          //  ((MediaBufferGroup*)handle)->mWrapper->init = nullptr; // enforce call-once
+            return true;
+        };
+
+        mWrapper->acquire_buffer = [](void *handle,
+                CMediaBufferV3 **buf, bool nonBlocking, size_t requestedSize) -> media_status_t {
+            MediaBufferBase *acquiredBuf = nullptr;
+            status_t err = ((MediaBufferGroup*)handle)->acquire_buffer(
+                    &acquiredBuf, nonBlocking, requestedSize);
+            if (err == OK && acquiredBuf != nullptr) {
+                *buf = acquiredBuf->wrap();
+            } else {
+                *buf = nullptr;
+            }
+            return translate_error(err);
+        };
+
+        mWrapper->has_buffers = [](void *handle) -> bool {
+            return ((MediaBufferGroup*)handle)->has_buffers();
+        };
+
+        return mWrapper;
+    }
+
 private:
+    CMediaBufferGroupV3 *mWrapper;
     struct InternalData;
     InternalData *mInternal;
 
     MediaBufferGroup(const MediaBufferGroup &);
     MediaBufferGroup &operator=(const MediaBufferGroup &);
+    void init(size_t buffers, size_t buffer_size, size_t growthLimit);
 };
 
 }  // namespace android
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 07e124b..0a342b8 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -31,8 +31,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 2109ad1..6b43375 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -78,9 +78,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
diff --git a/media/libmediaplayer2/JAudioTrack.cpp b/media/libmediaplayer2/JAudioTrack.cpp
index 7c2191b..a01afa3 100644
--- a/media/libmediaplayer2/JAudioTrack.cpp
+++ b/media/libmediaplayer2/JAudioTrack.cpp
@@ -439,31 +439,16 @@
 
 size_t JAudioTrack::frameSize() {
     JNIEnv *env = JavaVMHelper::getJNIEnv();
-
-    // TODO: Calculated here implementing the logic in AudioTrack.java
-    // wait for AudioTrack.java exposing this parameter (i.e. getFrameSizeInBtytes())
-    jmethodID jGetAudioFormat = env->GetMethodID(mAudioTrackCls, "getAudioFormat", "()I");
-    int javaFormat = env->CallIntMethod(mAudioTrackObj, jGetAudioFormat);
+    jmethodID jGetFormat = env->GetMethodID(mAudioTrackCls,
+            "getFormat", "()Landroid/media/AudioFormat;");
+    jobject jAudioFormatObj = env->CallObjectMethod(mAudioTrackObj, jGetFormat);
 
     jclass jAudioFormatCls = env->FindClass("android/media/AudioFormat");
-    jmethodID jIsEncodingLinearFrames = env->GetStaticMethodID(
-            jAudioFormatCls, "isEncodingLinearFrames", "(I)Z");
-    jboolean javaIsEncodingLinearFrames = env->CallStaticBooleanMethod(
-            jAudioFormatCls, jIsEncodingLinearFrames, javaFormat);
+    jmethodID jGetFrameSizeInBytes = env->GetMethodID(
+            jAudioFormatCls, "getFrameSizeInBytes", "()I");
+    jint javaFrameSizeInBytes = env->CallIntMethod(jAudioFormatObj, jGetFrameSizeInBytes);
 
-    if (javaIsEncodingLinearFrames == false) {
-        return 1;
-    }
-
-    jmethodID jGetBytesPerSample = env->GetStaticMethodID(jAudioFormatCls,
-            "getBytesPerSample", "(I)I");
-    int javaBytesPerSample = env->CallStaticIntMethod(jAudioFormatCls,
-            jGetBytesPerSample, javaFormat);
-
-    jmethodID jGetChannelCount = env->GetMethodID(mAudioTrackCls, "getChannelCount", "()I");
-    int javaChannelCount = env->CallIntMethod(mAudioTrackObj, jGetChannelCount);
-
-    return javaChannelCount * javaBytesPerSample;
+    return (size_t)javaFrameSizeInBytes;
 }
 
 status_t JAudioTrack::dump(int fd, const Vector<String16>& args __unused) const
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index 4b19e38..5e98589 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -260,11 +260,11 @@
     virtual void onMessageReceived(const sp<AMessage> & /* msg */) override { }
 
     // Modular DRM
-    virtual status_t prepareDrm(const uint8_t /* uuid */[16],
+    virtual status_t prepareDrm(int64_t /*srcId*/, const uint8_t /* uuid */[16],
                                 const Vector<uint8_t>& /* drmSessionId */) {
         return INVALID_OPERATION;
     }
-    virtual status_t releaseDrm() {
+    virtual status_t releaseDrm(int64_t /*srcId*/) {
         return INVALID_OPERATION;
     }
 
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index 4bc1a4a..c7cd7d2 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -105,8 +105,10 @@
             status_t        getParameter(int key, Parcel* reply);
 
             // Modular DRM
-            status_t        prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId);
-            status_t        releaseDrm();
+            status_t        prepareDrm(int64_t srcId,
+                                       const uint8_t uuid[16],
+                                       const Vector<uint8_t>& drmSessionId);
+            status_t        releaseDrm(int64_t srcId);
             // AudioRouting
             status_t        setPreferredDevice(jobject device);
             jobject         getRoutedDevice();
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index 921a5b7..2ae5a8c 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -1094,7 +1094,8 @@
 }
 
 // Modular DRM
-status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
+status_t MediaPlayer2::prepareDrm(
+        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId) {
     // TODO change to ALOGV
     ALOGD("prepareDrm: uuid: %p  drmSessionId: %p(%zu)", uuid,
             drmSessionId.array(), drmSessionId.size());
@@ -1118,7 +1119,7 @@
     }
 
     // Passing down to mediaserver mainly for creating the crypto
-    status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
+    status_t status = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
     ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
 
     // TODO change to ALOGV
@@ -1127,7 +1128,7 @@
     return status;
 }
 
-status_t MediaPlayer2::releaseDrm() {
+status_t MediaPlayer2::releaseDrm(int64_t srcId) {
     Mutex::Autolock _l(mLock);
     if (mPlayer == NULL) {
         return NO_INIT;
@@ -1142,7 +1143,7 @@
         return INVALID_OPERATION;
     }
 
-    status_t status = mPlayer->releaseDrm();
+    status_t status = mPlayer->releaseDrm(srcId);
     // TODO change to ALOGV
     ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
     if (status != OK) {
diff --git a/media/libmediaplayer2/nuplayer2/Android.bp b/media/libmediaplayer2/nuplayer2/Android.bp
index 93c218e..71cd50f 100644
--- a/media/libmediaplayer2/nuplayer2/Android.bp
+++ b/media/libmediaplayer2/nuplayer2/Android.bp
@@ -66,9 +66,6 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
index 2ea55f6..e53900b 100644
--- a/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/HTTPLiveSource2.cpp
@@ -273,10 +273,10 @@
 
         if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
             notify->post();
-            msg->post(delayUs > 0ll ? delayUs : 0ll);
+            msg->post(delayUs > 0LL ? delayUs : 0LL);
             return;
         } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
-            if (delayUs < -1000000ll) { // 1 second
+            if (delayUs < -1000000LL) { // 1 second
                 continue;
             }
             notify->post();
@@ -288,7 +288,7 @@
     }
 
     // try again in 1 second
-    msg->post(1000000ll);
+    msg->post(1000000LL);
 }
 
 void NuPlayer2::HTTPLiveSource2::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 6c4f0db..81ffbc7 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -240,8 +240,7 @@
       mVideoDecoderError(false),
       mPaused(false),
       mPausedByClient(true),
-      mPausedForBuffering(false),
-      mIsDrmProtected(false) {
+      mPausedForBuffering(false) {
     CHECK(mediaClock != NULL);
     clearFlushComplete();
 }
@@ -927,7 +926,7 @@
                 }
             }
 
-            msg->post(1000000ll);  // poll again in a second.
+            msg->post(1000000LL);  // poll again in a second.
             break;
         }
 
@@ -1195,7 +1194,7 @@
             }
 
             if (rescan) {
-                msg->post(100000ll);
+                msg->post(100000LL);
                 mScanSourcesPending = true;
             }
             break;
@@ -1630,7 +1629,7 @@
 
         case kWhatReleaseDrm:
         {
-            status_t status = onReleaseDrm();
+            status_t status = onReleaseDrm(msg);
 
             sp<AMessage> response = new AMessage;
             response->setInt32("status", status);
@@ -1672,7 +1671,7 @@
 }
 
 void NuPlayer2::onStart(bool play) {
-    ALOGV("onStart: mCrypto: %p", mCrypto.get());
+    ALOGV("onStart: mCrypto: %p", mCurrentSourceInfo.mCrypto.get());
 
     if (!mSourceStarted) {
         mSourceStarted = true;
@@ -1716,7 +1715,7 @@
                 && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
 
     // Modular DRM: Disabling audio offload if the source is protected
-    if (mOffloadAudio && mIsDrmProtected) {
+    if (mOffloadAudio && mCurrentSourceInfo.mIsDrmProtected) {
         mOffloadAudio = false;
         ALOGV("onStart: Disabling mOffloadAudio now that the source is protected.");
     }
@@ -2010,7 +2009,7 @@
                     && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
 
     // Modular DRM: Disabling audio offload if the source is protected
-    if (canOffload && mIsDrmProtected) {
+    if (canOffload && mCurrentSourceInfo.mIsDrmProtected) {
         canOffload = false;
         ALOGV("determineAudioModeChange: Disabling mOffloadAudio b/c the source is protected.");
     }
@@ -2117,10 +2116,11 @@
     (*decoder)->init();
 
     // Modular DRM
-    if (mIsDrmProtected) {
-        format->setObject("crypto", mCrypto);
+    if (mCurrentSourceInfo.mIsDrmProtected) {
+        format->setObject("crypto", mCurrentSourceInfo.mCrypto);
         ALOGV("instantiateDecoder: mCrypto: %p isSecure: %d",
-                mCrypto.get(), (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) != 0);
+                mCurrentSourceInfo.mCrypto.get(),
+                (mCurrentSourceInfo.mSourceFlags & Source::FLAG_SECURE) != 0);
     }
 
     (*decoder)->configure(format);
@@ -2506,12 +2506,8 @@
     mRenderer.clear();
     ++mRendererGeneration;
 
-    if (mCurrentSourceInfo.mSource != NULL) {
-        mCurrentSourceInfo.mSource->stop();
-
-        Mutex::Autolock autoLock(mSourceLock);
-        mCurrentSourceInfo.mSource.clear();
-    }
+    resetSourceInfo(mCurrentSourceInfo);
+    resetSourceInfo(mNextSourceInfo);
 
     if (mDriver != NULL) {
         sp<NuPlayer2Driver> driver = mDriver.promote();
@@ -2525,14 +2521,6 @@
     mResetting = false;
     mSourceStarted = false;
 
-    // Modular DRM
-    if (mCrypto != NULL) {
-        // decoders will be flushed before this so their mCrypto would go away on their own
-        // TODO change to ALOGV
-        ALOGD("performReset mCrypto: %p", mCrypto.get());
-        mCrypto.clear();
-    }
-    mIsDrmProtected = false;
 }
 
 void NuPlayer2::performPlayNextDataSource() {
@@ -2586,15 +2574,6 @@
 
     addEndTimeMonitor();
 
-    // Modular DRM
-    if (mCrypto != NULL) {
-        // decoders will be flushed before this so their mCrypto would go away on their own
-        // TODO change to ALOGV
-        ALOGD("performReset mCrypto: %p", mCrypto.get());
-        mCrypto.clear();
-    }
-    mIsDrmProtected = false;
-
     if (mRenderer != NULL) {
         mRenderer->resume();
     }
@@ -2891,7 +2870,7 @@
             int64_t posMs;
             int64_t timeUs, posUs;
             driver->getCurrentPosition(&posMs);
-            posUs = posMs * 1000ll;
+            posUs = posMs * 1000LL;
             CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
 
             if (posUs < timeUs) {
@@ -3045,8 +3024,34 @@
     }
  }
 
+NuPlayer2::SourceInfo* NuPlayer2::getSourceInfoByIdInMsg(const sp<AMessage> &msg) {
+    int64_t srcId;
+    CHECK(msg->findInt64("srcId", &srcId));
+    if (mCurrentSourceInfo.mSrcId == srcId) {
+        return &mCurrentSourceInfo;
+    } else if (mNextSourceInfo.mSrcId == srcId) {
+        return &mNextSourceInfo;
+    } else {
+        return NULL;
+    }
+}
+
+void NuPlayer2::resetSourceInfo(NuPlayer2::SourceInfo &srcInfo) {
+    if (srcInfo.mSource != NULL) {
+        srcInfo.mSource->stop();
+
+        Mutex::Autolock autoLock(mSourceLock);
+        srcInfo.mSource.clear();
+    }
+    // Modular DRM
+    ALOGD("performReset mCrypto: %p", srcInfo.mCrypto.get());
+    srcInfo.mCrypto.clear();
+    srcInfo.mIsDrmProtected = false;
+}
+
 // Modular DRM begin
-status_t NuPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
+status_t NuPlayer2::prepareDrm(
+        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
 {
     ALOGV("prepareDrm ");
 
@@ -3056,6 +3061,7 @@
     uint8_t UUID[16];
     memcpy(UUID, uuid, sizeof(UUID));
     Vector<uint8_t> sessionId = drmSessionId;
+    msg->setInt64("srcId", srcId);
     msg->setPointer("uuid", (void*)UUID);
     msg->setPointer("drmSessionId", (void*)&sessionId);
 
@@ -3072,11 +3078,12 @@
     return status;
 }
 
-status_t NuPlayer2::releaseDrm()
+status_t NuPlayer2::releaseDrm(int64_t srcId)
 {
     ALOGV("releaseDrm ");
 
     sp<AMessage> msg = new AMessage(kWhatReleaseDrm, this);
+    msg->setInt64("srcId", srcId);
 
     sp<AMessage> response;
     status_t status = msg->postAndAwaitResponse(&response);
@@ -3097,8 +3104,15 @@
     ALOGD("onPrepareDrm ");
 
     status_t status = INVALID_OPERATION;
-    if (mCurrentSourceInfo.mSource == NULL) {
-        ALOGE("onPrepareDrm: No source. onPrepareDrm failed with %d.", status);
+    SourceInfo *srcInfo = getSourceInfoByIdInMsg(msg);
+    if (srcInfo == NULL) {
+        return status;
+    }
+
+    int64_t srcId = srcInfo->mSrcId;
+    if (srcInfo->mSource == NULL) {
+        ALOGE("onPrepareDrm: srcInfo(%lld) No source. onPrepareDrm failed with %d.",
+                (long long)srcId, status);
         return status;
     }
 
@@ -3110,42 +3124,50 @@
     status = OK;
     sp<AMediaCryptoWrapper> crypto = NULL;
 
-    status = mCurrentSourceInfo.mSource->prepareDrm(uuid, *drmSessionId, &crypto);
+    status = srcInfo->mSource->prepareDrm(uuid, *drmSessionId, &crypto);
     if (crypto == NULL) {
-        ALOGE("onPrepareDrm: mCurrentSourceInfo.mSource->prepareDrm failed. status: %d", status);
+        ALOGE("onPrepareDrm: srcInfo(%lld).mSource->prepareDrm failed. status: %d",
+                (long long)srcId, status);
         return status;
     }
-    ALOGV("onPrepareDrm: mCurrentSourceInfo.mSource->prepareDrm succeeded");
+    ALOGV("onPrepareDrm: srcInfo(%lld).mSource->prepareDrm succeeded", (long long)srcId);
 
-    if (mCrypto != NULL) {
-        ALOGE("onPrepareDrm: Unexpected. Already having mCrypto: %p", mCrypto.get());
-        mCrypto.clear();
+    if (srcInfo->mCrypto != NULL) {
+        ALOGE("onPrepareDrm: srcInfo(%lld) Unexpected. Already having mCrypto: %p",
+                (long long)srcId, srcInfo->mCrypto.get());
+        srcInfo->mCrypto.clear();
     }
 
-    mCrypto = crypto;
-    mIsDrmProtected = true;
+    srcInfo->mCrypto = crypto;
+    srcInfo->mIsDrmProtected = true;
     // TODO change to ALOGV
-    ALOGD("onPrepareDrm: mCrypto: %p", mCrypto.get());
+    ALOGD("onPrepareDrm: mCrypto: %p", srcInfo->mCrypto.get());
 
     return status;
 }
 
-status_t NuPlayer2::onReleaseDrm()
+status_t NuPlayer2::onReleaseDrm(const sp<AMessage> &msg)
 {
     // TODO change to ALOGV
     ALOGD("onReleaseDrm ");
-
-    if (!mIsDrmProtected) {
-        ALOGW("onReleaseDrm: Unexpected. mIsDrmProtected is already false.");
+    SourceInfo *srcInfo = getSourceInfoByIdInMsg(msg);;
+    if (srcInfo == NULL) {
+        return INVALID_OPERATION;
     }
 
-    mIsDrmProtected = false;
+    int64_t srcId = srcInfo->mSrcId;
+    if (!srcInfo->mIsDrmProtected) {
+        ALOGW("onReleaseDrm: srcInfo(%lld) Unexpected. mIsDrmProtected is already false.",
+                (long long)srcId);
+    }
+
+    srcInfo->mIsDrmProtected = false;
 
     status_t status;
-    if (mCrypto != NULL) {
+    if (srcInfo->mCrypto != NULL) {
         // notifying the source first before removing crypto from codec
-        if (mCurrentSourceInfo.mSource != NULL) {
-            mCurrentSourceInfo.mSource->releaseDrm();
+        if (srcInfo->mSource != NULL) {
+            srcInfo->mSource->releaseDrm();
         }
 
         status=OK;
@@ -3166,9 +3188,9 @@
         }
 
         // TODO change to ALOGV
-        ALOGD("onReleaseDrm: mCrypto: %p", mCrypto.get());
-        mCrypto.clear();
-    } else {   // mCrypto == NULL
+        ALOGD("onReleaseDrm: mCrypto: %p", srcInfo->mCrypto.get());
+        srcInfo->mCrypto.clear();
+    } else {   // srcInfo->mCrypto == NULL
         ALOGE("onReleaseDrm: Unexpected. There is no crypto.");
         status = INVALID_OPERATION;
     }
@@ -3240,11 +3262,13 @@
 
 NuPlayer2::SourceInfo & NuPlayer2::SourceInfo::operator=(const NuPlayer2::SourceInfo &other) {
     mSource = other.mSource;
+    mCrypto = other.mCrypto;
     mDataSourceType = (DATA_SOURCE_TYPE)other.mDataSourceType;
     mSrcId = other.mSrcId;
     mSourceFlags = other.mSourceFlags;
     mStartTimeUs = other.mStartTimeUs;
     mEndTimeUs = other.mEndTimeUs;
+    mIsDrmProtected = other.mIsDrmProtected;
     return *this;
 }
 
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index 3ecdb01..e9b5f11 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -92,8 +92,8 @@
     float getFrameRate();
 
     // Modular DRM
-    status_t prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
-    status_t releaseDrm();
+    status_t prepareDrm(int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
+    status_t releaseDrm(int64_t srcId);
 
     const char *getDataSourceType();
 
@@ -178,6 +178,9 @@
         uint32_t mSourceFlags;
         int64_t mStartTimeUs;
         int64_t mEndTimeUs;
+        // Modular DRM
+        sp<AMediaCryptoWrapper> mCrypto;
+        bool mIsDrmProtected = false;
     };
 
     wp<NuPlayer2Driver> mDriver;
@@ -269,10 +272,6 @@
     // Pause state as requested by source (internally) due to buffering
     bool mPausedForBuffering;
 
-    // Modular DRM
-    sp<AMediaCryptoWrapper> mCrypto;
-    bool mIsDrmProtected;
-
     inline const sp<DecoderBase> &getDecoder(bool audio) {
         return audio ? mAudioDecoder : mVideoDecoder;
     }
@@ -351,7 +350,10 @@
     void writeTrackInfo(PlayerMessage* reply, const sp<AMessage>& format) const;
 
     status_t onPrepareDrm(const sp<AMessage> &msg);
-    status_t onReleaseDrm();
+    status_t onReleaseDrm(const sp<AMessage> &msg);
+
+    SourceInfo* getSourceInfoByIdInMsg(const sp<AMessage> &msg);
+    void resetSourceInfo(SourceInfo &srcInfo);
 
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayer2);
 };
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp
index a9f2104..98c3403 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2CCDecoder.cpp
@@ -567,7 +567,7 @@
 
         ccBuf->meta()->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, mSelectedTrack);
         ccBuf->meta()->setInt64("timeUs", timeUs);
-        ccBuf->meta()->setInt64("durationUs", 0ll);
+        ccBuf->meta()->setInt64("durationUs", 0LL);
 
         sp<AMessage> msg = mNotify->dup();
         msg->setInt32("what", kWhatClosedCaptionData);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
index 931b86e..49e3e3b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
@@ -71,10 +71,10 @@
       mCCDecoder(ccDecoder),
       mPid(pid),
       mUid(uid),
-      mSkipRenderingUntilMediaTimeUs(-1ll),
-      mNumFramesTotal(0ll),
-      mNumInputFramesDropped(0ll),
-      mNumOutputFramesDropped(0ll),
+      mSkipRenderingUntilMediaTimeUs(-1LL),
+      mNumFramesTotal(0LL),
+      mNumInputFramesDropped(0LL),
+      mNumOutputFramesDropped(0LL),
       mVideoWidth(0),
       mVideoHeight(0),
       mIsAudio(true),
@@ -428,10 +428,10 @@
         // TODO: For now, layer fps is calculated for some specific architectures.
         // But it really should be extracted from the stream.
         mVideoTemporalLayerAggregateFps[0] =
-            mFrameRateTotal / (float)(1ll << (mNumVideoTemporalLayerTotal - 1));
+            mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - 1));
         for (int32_t i = 1; i < mNumVideoTemporalLayerTotal; ++i) {
             mVideoTemporalLayerAggregateFps[i] =
-                mFrameRateTotal / (float)(1ll << (mNumVideoTemporalLayerTotal - i))
+                mFrameRateTotal / (float)(1LL << (mNumVideoTemporalLayerTotal - i))
                 + mVideoTemporalLayerAggregateFps[i - 1];
         }
     }
@@ -952,7 +952,7 @@
 
             int32_t layerId = 0;
             bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
-            if (mRenderer->getVideoLateByUs() > 100000ll
+            if (mRenderer->getVideoLateByUs() > 100000LL
                     && mIsVideoAVC
                     && !IsAVCReferenceFrame(accessUnit)) {
                 dropAccessUnit = true;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp
index 1f1b69e..914f29f 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderBase.cpp
@@ -122,7 +122,7 @@
         mRequestInputBuffersPending = true;
 
         sp<AMessage> msg = new AMessage(kWhatRequestInputBuffers, this);
-        msg->post(10 * 1000ll);
+        msg->post(10 * 1000LL);
     }
 }
 
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp
index 0e0c1d8..0514e88 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2DecoderPassThrough.cpp
@@ -46,7 +46,7 @@
     : DecoderBase(notify),
       mSource(source),
       mRenderer(renderer),
-      mSkipRenderingUntilMediaTimeUs(-1ll),
+      mSkipRenderingUntilMediaTimeUs(-1LL),
       mReachedEOS(true),
       mPendingAudioErr(OK),
       mPendingBuffersToDrain(0),
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 821dc9f..56d708a 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -372,7 +372,7 @@
     ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
     Mutex::Autolock autoLock(mLock);
 
-    int64_t seekTimeUs = msec * 1000ll;
+    int64_t seekTimeUs = msec * 1000LL;
 
     switch (mState) {
         case STATE_PREPARED:
@@ -426,7 +426,7 @@
         return UNKNOWN_ERROR;
     }
 
-    *msec = (mDurationUs + 500ll) / 1000;
+    *msec = (mDurationUs + 500LL) / 1000;
 
     return OK;
 }
@@ -612,7 +612,7 @@
             int64_t msec = 0;
             // getCurrentPosition should always return OK
             getCurrentPosition(&msec);
-            return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
+            return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000LL);
         }
 
         case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
@@ -976,24 +976,25 @@
 }
 
 // Modular DRM
-status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
+status_t NuPlayer2Driver::prepareDrm(
+        int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
 {
     ALOGV("prepareDrm(%p) state: %d", this, mState);
 
     // leaving the state verification for mediaplayer.cpp
-    status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
+    status_t ret = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
 
     ALOGV("prepareDrm ret: %d", ret);
 
     return ret;
 }
 
-status_t NuPlayer2Driver::releaseDrm()
+status_t NuPlayer2Driver::releaseDrm(int64_t srcId)
 {
     ALOGV("releaseDrm(%p) state: %d", this, mState);
 
     // leaving the state verification for mediaplayer.cpp
-    status_t ret = mPlayer->releaseDrm();
+    status_t ret = mPlayer->releaseDrm(srcId);
 
     ALOGV("releaseDrm ret: %d", ret);
 
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
index 50ee173..bb30c76 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
@@ -82,8 +82,9 @@
     void notifyFlagsChanged(int64_t srcId, uint32_t flags);
 
     // Modular DRM
-    virtual status_t prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
-    virtual status_t releaseDrm();
+    virtual status_t prepareDrm(
+            int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId);
+    virtual status_t releaseDrm(int64_t srcId);
 
 protected:
     virtual ~NuPlayer2Driver();
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index d800412..9d9e179 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -67,10 +67,10 @@
 
 // Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
 // is closed to allow the audio DSP to power down.
-static const int64_t kOffloadPauseMaxUs = 10000000ll;
+static const int64_t kOffloadPauseMaxUs = 10000000LL;
 
 // Maximum allowed delay from AudioSink, 1.5 seconds.
-static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll;
+static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000LL;
 
 static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
 
@@ -84,7 +84,7 @@
 };
 
 // static
-const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000ll;
+const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000LL;
 
 NuPlayer2::Renderer::Renderer(
         const sp<MediaPlayer2Interface::AudioSink> &sink,
@@ -108,7 +108,7 @@
       mAudioFirstAnchorTimeMediaUs(-1),
       mAnchorTimeMediaUs(-1),
       mAnchorNumFramesWritten(-1),
-      mVideoLateByUs(0ll),
+      mVideoLateByUs(0LL),
       mNextVideoTimeMediaUs(-1),
       mHasAudio(false),
       mHasVideo(false),
@@ -1142,7 +1142,7 @@
         int64_t nowUs = ALooper::GetNowUs();
         int64_t mediaUs;
         if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
-            return 0ll;
+            return 0LL;
         } else {
             return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
         }
@@ -1357,7 +1357,7 @@
         tooLate = false;
     }
 
-    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
+    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
     entry->mNotifyConsumed->setInt32("render", !tooLate);
     entry->mNotifyConsumed->post();
     mVideoQueue.erase(mVideoQueue.begin());
@@ -1489,7 +1489,7 @@
 
     ALOGV("queueDiff = %.2f secs", diff / 1E6);
 
-    if (diff > 100000ll) {
+    if (diff > 100000LL) {
         // Audio data starts More than 0.1 secs before video.
         // Drop some audio.
 
diff --git a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp b/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
index aed925b..a70269e 100644
--- a/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/RTSPSource2.cpp
@@ -30,7 +30,7 @@
 
 namespace android {
 
-const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+const int64_t kNearEOSTimeoutUs = 2000000LL; // 2 secs
 
 // Default Buffer Underflow/Prepare/StartServer/Overflow Marks
 static const int kUnderflowMarkMs   =  1000;  // 1 second
@@ -168,7 +168,7 @@
     // We're going to buffer at least 2 secs worth data on all tracks before
     // starting playback (both at startup and after a seek).
 
-    static const int64_t kMinDurationUs = 2000000ll;
+    static const int64_t kMinDurationUs = 2000000LL;
 
     int64_t mediaDurationUs = 0;
     getDuration(&mediaDurationUs);
@@ -272,7 +272,7 @@
 }
 
 status_t NuPlayer2::RTSPSource2::getDuration(int64_t *durationUs) {
-    *durationUs = -1ll;
+    *durationUs = -1LL;
 
     int64_t audioDurationUs;
     if (mAudioTrack != NULL
@@ -321,7 +321,7 @@
 
 void NuPlayer2::RTSPSource2::schedulePollBuffering() {
     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
-    msg->post(1000000ll); // 1 second intervals
+    msg->post(1000000LL); // 1 second intervals
 }
 
 void NuPlayer2::RTSPSource2::checkBuffering(
@@ -345,10 +345,10 @@
         int64_t maxRebufferingMarkUs;
         {
             Mutex::Autolock _l(mBufferingSettingsLock);
-            initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000ll;
+            initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
             // TODO: maxRebufferingMarkUs could be larger than
             // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
-            maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000ll;
+            maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
         }
         // isFinished when duration is 0 checks for EOS result only
         if (bufferedDurationUs > initialMarkUs
@@ -368,7 +368,7 @@
                 ++overflowCount;
             }
             int64_t startServerMarkUs =
-                    (kUnderflowMarkMs * 1000ll + maxRebufferingMarkUs) / 2;
+                    (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
             if (bufferedDurationUs < startServerMarkUs) {
                 ++startCount;
             }
@@ -639,7 +639,7 @@
                 int64_t nptUs =
                     ((double)rtpTime - (double)info->mRTPTime)
                         / info->mTimeScale
-                        * 1000000ll
+                        * 1000000LL
                         + info->mNormalPlaytimeUs;
 
                 accessUnit->meta()->setInt64("timeUs", nptUs);
@@ -747,7 +747,7 @@
         TrackInfo info;
         info.mTimeScale = timeScale;
         info.mRTPTime = 0;
-        info.mNormalPlaytimeUs = 0ll;
+        info.mNormalPlaytimeUs = 0LL;
         info.mNPTMappingValid = false;
 
         if ((isAudio && mAudioTrack == NULL)
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 09b19d7..51879fd 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -68,9 +68,6 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index a4da564..23a19e7 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -56,9 +56,6 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3080db5..f4b5600 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2237,6 +2237,15 @@
         } else {
             err = setupEAC3Codec(encoder, numChannels, sampleRate);
         }
+     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC4)) {
+        int32_t numChannels;
+        int32_t sampleRate;
+        if (!msg->findInt32("channel-count", &numChannels)
+                || !msg->findInt32("sample-rate", &sampleRate)) {
+            err = INVALID_OPERATION;
+        } else {
+            err = setupAC4Codec(encoder, numChannels, sampleRate);
+        }
     }
 
     if (err != OK) {
@@ -2893,6 +2902,38 @@
             (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
 }
 
+status_t ACodec::setupAC4Codec(
+        bool encoder, int32_t numChannels, int32_t sampleRate) {
+    status_t err = setupRawAudioFormat(
+            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (encoder) {
+        ALOGW("AC4 encoding is not supported.");
+        return INVALID_OPERATION;
+    }
+
+    OMX_AUDIO_PARAM_ANDROID_AC4TYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = mOMXNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc4, &def, sizeof(def));
+
+    if (err != OK) {
+        return err;
+    }
+
+    def.nChannels = numChannels;
+    def.nSampleRate = sampleRate;
+
+    return mOMXNode->setParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc4, &def, sizeof(def));
+}
+
 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
         bool isAMRWB, int32_t bps) {
     if (isAMRWB) {
@@ -5246,6 +5287,25 @@
                     break;
                 }
 
+                case OMX_AUDIO_CodingAndroidAC4:
+                {
+                    OMX_AUDIO_PARAM_ANDROID_AC4TYPE params;
+                    InitOMXParams(&params);
+                    params.nPortIndex = portIndex;
+
+                    err = mOMXNode->getParameter(
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc4,
+                            &params, sizeof(params));
+                    if (err != OK) {
+                        return err;
+                    }
+
+                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC4);
+                    notify->setInt32("channel-count", params.nChannels);
+                    notify->setInt32("sample-rate", params.nSampleRate);
+                    break;
+                }
+
                 case OMX_AUDIO_CodingAndroidOPUS:
                 {
                     OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index cc5b7da..02bb4e0 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -18,9 +18,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: ["libmedia"],
@@ -40,9 +37,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: ["libmedia", "libmediandk"],
@@ -80,9 +74,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -146,6 +137,7 @@
 
     shared_libs: [
         "libaudioutils",
+        "libbase",
         "libbinder",
         "libcamera_client",
         "libcutils",
@@ -206,12 +198,6 @@
         "include",
     ],
 
-    // This is needed to make sure libcodec2 exists in all devices.
-    // TODO: Remove this once the public CCodec is enabled.
-    required: [
-        "libcodec2",
-    ],
-
     cflags: [
         "-Wno-multichar",
         "-Werror",
@@ -234,9 +220,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -291,9 +274,6 @@
             "unsigned-integer-overflow",
             "signed-integer-overflow",
         ],
-        diag: {
-            cfi: true,
-        },
     },
 }
 
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index ac9eb0b..ea818ff 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -134,4 +134,57 @@
     return plugin->setMediaCas(plugin->data, casToken, size);
 }
 
+// --------------------------------------------------------------------------------
+MediaExtractorCUnwrapperV3::MediaExtractorCUnwrapperV3(CMediaExtractorV3 *plugin) {
+    this->plugin = plugin;
+}
+
+MediaExtractorCUnwrapperV3::~MediaExtractorCUnwrapperV3() {
+    plugin->free(plugin->data);
+    free(plugin);
+}
+
+size_t MediaExtractorCUnwrapperV3::countTracks() {
+    return plugin->countTracks(plugin->data);
+}
+
+MediaTrack *MediaExtractorCUnwrapperV3::getTrack(size_t index) {
+    return new MediaTrackCUnwrapperV3(plugin->getTrack(plugin->data, index));
+}
+
+status_t MediaExtractorCUnwrapperV3::getTrackMetaData(
+        MetaDataBase& meta, size_t index, uint32_t flags) {
+    sp<AMessage> msg = new AMessage();
+    AMediaFormat *format =  AMediaFormat_fromMsg(&msg);
+    media_status_t ret = plugin->getTrackMetaData(plugin->data, format, index, flags);
+    sp<MetaData> newMeta = new MetaData();
+    convertMessageToMetaData(msg, newMeta);
+    delete format;
+    meta = *newMeta;
+    return reverse_translate_error(ret);
+}
+
+status_t MediaExtractorCUnwrapperV3::getMetaData(MetaDataBase& meta) {
+    sp<AMessage> msg = new AMessage();
+    AMediaFormat *format =  AMediaFormat_fromMsg(&msg);
+    media_status_t ret = plugin->getMetaData(plugin->data, format);
+    sp<MetaData> newMeta = new MetaData();
+    convertMessageToMetaData(msg, newMeta);
+    delete format;
+    meta = *newMeta;
+    return reverse_translate_error(ret);
+}
+
+const char * MediaExtractorCUnwrapperV3::name() {
+    return plugin->name(plugin->data);
+}
+
+uint32_t MediaExtractorCUnwrapperV3::flags() const {
+    return plugin->flags(plugin->data);
+}
+
+status_t MediaExtractorCUnwrapperV3::setMediaCas(const uint8_t* casToken, size_t size) {
+    return plugin->setMediaCas(plugin->data, casToken, size);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 318c1eb..81fc4ae 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "MediaExtractorFactory"
 #include <utils/Log.h>
 
+#include <android/dlext.h>
 #include <binder/IPCThreadState.h>
 #include <binder/PermissionCache.h>
 #include <binder/IServiceManager.h>
@@ -36,6 +37,23 @@
 #include <dirent.h>
 #include <dlfcn.h>
 
+// Copied from GraphicsEnv.cpp
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+  android_namespace_t* android_create_namespace(const char* name,
+                                                const char* ld_library_path,
+                                                const char* default_library_path,
+                                                uint64_t type,
+                                                const char* permitted_when_isolated_path,
+                                                android_namespace_t* parent);
+  bool android_link_namespaces(android_namespace_t* from,
+                               android_namespace_t* to,
+                               const char* shared_libs_sonames);
+  enum {
+     ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+  };
+}
+
 namespace android {
 
 // static
@@ -100,6 +118,12 @@
             freeMeta(meta);
         }
         ex = ret != nullptr ? new MediaExtractorCUnwrapperV2(ret) : nullptr;
+    } else if (creatorVersion == 3) {
+        CMediaExtractorV3 *ret = ((CreatorFuncV3)creator)(source->wrap(), meta);
+        if (meta != nullptr && freeMeta != nullptr) {
+            freeMeta(meta);
+        }
+        ex = ret != nullptr ? new MediaExtractorCUnwrapperV3(ret) : nullptr;
     }
 
     ALOGV("Created an extractor '%s' with confidence %.2f",
@@ -139,6 +163,13 @@
 std::shared_ptr<std::list<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins;
 bool MediaExtractorFactory::gPluginsRegistered = false;
 bool MediaExtractorFactory::gIgnoreVersion = false;
+std::string MediaExtractorFactory::gLinkedLibraries;
+
+// static
+void MediaExtractorFactory::SetLinkedLibraries(const std::string& linkedLibraries) {
+    Mutex::Autolock autoLock(gPluginMutex);
+    gLinkedLibraries = linkedLibraries;
+}
 
 // static
 void *MediaExtractorFactory::sniff(
@@ -170,6 +201,9 @@
         } else if ((*it)->def.def_version == 2) {
             curCreator = (void*) (*it)->def.sniff.v2(
                     source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
+        } else if ((*it)->def.def_version == 3) {
+            curCreator = (void*) (*it)->def.sniff.v3(
+                    source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
         }
 
         if (curCreator) {
@@ -199,7 +233,7 @@
         std::list<sp<ExtractorPlugin>> &pluginList) {
     // sanity check check struct version, uuid, name
     if (plugin->def.def_version == 0
-            || plugin->def.def_version > EXTRACTORDEF_VERSION_CURRENT) {
+            || plugin->def.def_version > EXTRACTORDEF_VERSION_CURRENT + 1) {
         ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
         return;
     }
@@ -319,6 +353,62 @@
     }
 }
 
+//static
+void MediaExtractorFactory::RegisterExtractorsInApex(
+        const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList) {
+    ALOGV("search for plugins at %s", libDirPath);
+    ALOGV("linked libs %s", gLinkedLibraries.c_str());
+
+    android_namespace_t *extractorNs = android_create_namespace("extractor",
+            nullptr,  // ld_library_path
+            libDirPath,
+            ANDROID_NAMESPACE_TYPE_ISOLATED,
+            nullptr,  // permitted_when_isolated_path
+            nullptr); // parent
+    if (!android_link_namespaces(extractorNs, nullptr, gLinkedLibraries.c_str())) {
+        ALOGE("Failed to link namespace. Failed to load extractor plug-ins in apex.");
+        return;
+    }
+    const android_dlextinfo dlextinfo = {
+        .flags = ANDROID_DLEXT_USE_NAMESPACE,
+        .library_namespace = extractorNs,
+    };
+
+    DIR *libDir = opendir(libDirPath);
+    if (libDir) {
+        struct dirent* libEntry;
+        while ((libEntry = readdir(libDir))) {
+            if (libEntry->d_name[0] == '.') {
+                continue;
+            }
+            String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
+            if (!libPath.contains("extractor.so")) {
+                continue;
+            }
+            void *libHandle = android_dlopen_ext(
+                    libPath.string(),
+                    RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+            if (libHandle) {
+                GetExtractorDef getDef =
+                    (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+                if (getDef) {
+                    ALOGV("registering sniffer for %s", libPath.string());
+                    RegisterExtractor(
+                            new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+                } else {
+                    ALOGW("%s does not contain sniffer", libPath.string());
+                    dlclose(libHandle);
+                }
+            } else {
+                ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
+            }
+        }
+        closedir(libDir);
+    } else {
+        ALOGE("couldn't opendir(%s)", libDirPath);
+    }
+}
+
 static bool compareFunc(const sp<ExtractorPlugin>& first, const sp<ExtractorPlugin>& second) {
     return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
 }
@@ -337,6 +427,12 @@
 
     std::shared_ptr<std::list<sp<ExtractorPlugin>>> newList(new std::list<sp<ExtractorPlugin>>());
 
+    RegisterExtractorsInApex("/apex/com.android.media/lib"
+#ifdef __LP64__
+            "64"
+#endif
+            , *newList);
+
     RegisterExtractorsInSystem("/system/lib"
 #ifdef __LP64__
             "64"
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 821605d..6c0f989 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -155,4 +155,80 @@
     return wrapper->supportsNonBlockingRead(wrapper->data);
 }
 
+/* -------------- unwrapper v3 --------------- */
+
+MediaTrackCUnwrapperV3::MediaTrackCUnwrapperV3(CMediaTrackV3 *cmediatrack3) {
+    wrapper = cmediatrack3;
+    bufferGroup = nullptr;
+}
+
+MediaTrackCUnwrapperV3::~MediaTrackCUnwrapperV3() {
+    wrapper->free(wrapper->data);
+    free(wrapper);
+}
+
+status_t MediaTrackCUnwrapperV3::start() {
+    if (bufferGroup == nullptr) {
+        bufferGroup = new MediaBufferGroup();
+    }
+    return reverse_translate_error(wrapper->start(wrapper->data, bufferGroup->wrap()));
+}
+
+status_t MediaTrackCUnwrapperV3::stop() {
+    return reverse_translate_error(wrapper->stop(wrapper->data));
+}
+
+status_t MediaTrackCUnwrapperV3::getFormat(MetaDataBase& format) {
+    sp<AMessage> msg = new AMessage();
+    AMediaFormat *tmpFormat =  AMediaFormat_fromMsg(&msg);
+    media_status_t ret = wrapper->getFormat(wrapper->data, tmpFormat);
+    sp<MetaData> newMeta = new MetaData();
+    convertMessageToMetaData(msg, newMeta);
+    delete tmpFormat;
+    format = *newMeta;
+    return reverse_translate_error(ret);
+}
+
+status_t MediaTrackCUnwrapperV3::read(MediaBufferBase **buffer, const ReadOptions *options) {
+
+    uint32_t opts = 0;
+
+    if (options && options->getNonBlocking()) {
+        opts |= CMediaTrackReadOptions::NONBLOCKING;
+    }
+
+    int64_t seekPosition = 0;
+    MediaTrack::ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekPosition, &seekMode)) {
+        opts |= SEEK;
+        opts |= (uint32_t) seekMode;
+    }
+    CMediaBufferV3 *buf = nullptr;
+    media_status_t ret = wrapper->read(wrapper->data, &buf, opts, seekPosition);
+    if (ret == AMEDIA_OK && buf != nullptr) {
+        *buffer = (MediaBufferBase*)buf->handle;
+        MetaDataBase &meta = (*buffer)->meta_data();
+        AMediaFormat *format = buf->meta_data(buf->handle);
+        // only convert the keys we're actually expecting, as doing
+        // the full convertMessageToMetadata() for every buffer is
+        // too expensive
+        int64_t val64;
+        if (format->mFormat->findInt64("timeUs", &val64)) {
+            meta.setInt64(kKeyTime, val64);
+        }
+        int32_t val32;
+        if (format->mFormat->findInt32("is-sync-frame", &val32)) {
+            meta.setInt32(kKeyIsSyncFrame, val32);
+        }
+    } else {
+        *buffer = nullptr;
+    }
+
+    return reverse_translate_error(ret);
+}
+
+bool MediaTrackCUnwrapperV3::supportNonblockingRead() {
+    return wrapper->supportsNonBlockingRead(wrapper->data);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.cpp b/media/libstagefright/StagefrightPluginLoader.cpp
index dd5903a..b90649c 100644
--- a/media/libstagefright/StagefrightPluginLoader.cpp
+++ b/media/libstagefright/StagefrightPluginLoader.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "StagefrightPluginLoader"
 #include <utils/Log.h>
 
+#include <android-base/properties.h>
 #include <dlfcn.h>
 
 #include "StagefrightPluginLoader.h"
@@ -27,9 +28,17 @@
 /* static */ Mutex StagefrightPluginLoader::sMutex;
 /* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
 
-StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath)
-    : mCreateCodec(nullptr),
-      mCreateBuilder(nullptr) {
+namespace /* unnamed */ {
+
+constexpr const char kCCodecPluginPath[] = "libsfplugin_ccodec.so";
+
+}  // unnamed namespace
+
+StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath) {
+    if (android::base::GetIntProperty("debug.media.codec2", 0) == 0) {
+        ALOGD("CCodec is disabled.");
+        return;
+    }
     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
     if (mLibHandle == nullptr) {
         ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
@@ -87,7 +96,7 @@
     Mutex::Autolock _l(sMutex);
     if (!sInstance) {
         ALOGV("Loading library");
-        sInstance.reset(new StagefrightPluginLoader("libstagefright_ccodec.so"));
+        sInstance.reset(new StagefrightPluginLoader(kCCodecPluginPath));
     }
     return sInstance;
 }
diff --git a/media/libstagefright/StagefrightPluginLoader.h b/media/libstagefright/StagefrightPluginLoader.h
index 999d30c..78effbf 100644
--- a/media/libstagefright/StagefrightPluginLoader.h
+++ b/media/libstagefright/StagefrightPluginLoader.h
@@ -40,10 +40,10 @@
     static Mutex sMutex;
     static std::unique_ptr<StagefrightPluginLoader> sInstance;
 
-    void *mLibHandle;
-    CodecBase::CreateCodecFunc mCreateCodec;
-    MediaCodecListBuilderBase::CreateBuilderFunc mCreateBuilder;
-    CodecBase::CreateInputSurfaceFunc mCreateInputSurface;
+    void *mLibHandle{nullptr};
+    CodecBase::CreateCodecFunc mCreateCodec{nullptr};
+    MediaCodecListBuilderBase::CreateBuilderFunc mCreateBuilder{nullptr};
+    CodecBase::CreateInputSurfaceFunc mCreateInputSurface{nullptr};
 };
 
 }  // namespace android
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 53c32b2..670b607 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -588,10 +588,17 @@
     }
 };
 
+static std::vector<std::pair<const char *, uint32_t>> floatMappings {
+    {
+        { "capture-rate", kKeyCaptureFramerate },
+    }
+};
+
 static std::vector<std::pair<const char *, uint32_t>> int64Mappings {
     {
         { "exif-offset", kKeyExifOffset },
         { "exif-size", kKeyExifSize },
+        { "thumbnail-time", kKeyThumbnailTime },
     }
 };
 
@@ -632,6 +639,13 @@
         }
     }
 
+    for (auto elem : floatMappings) {
+        float value;
+        if (msg->findFloat(elem.first, &value)) {
+            meta->setFloat(elem.second, value);
+        }
+    }
+
     for (auto elem : int64Mappings) {
         int64_t value;
         if (msg->findInt64(elem.first, &value)) {
@@ -663,6 +677,13 @@
         }
     }
 
+    for (auto elem : floatMappings) {
+        float value;
+        if (meta->findFloat(elem.second, &value)) {
+            format->setFloat(elem.first, value);
+        }
+    }
+
     for (auto elem : int64Mappings) {
         int64_t value;
         if (meta->findInt64(elem.second, &value)) {
@@ -1801,6 +1822,7 @@
     { MEDIA_MIMETYPE_AUDIO_OPUS,        AUDIO_FORMAT_OPUS},
     { MEDIA_MIMETYPE_AUDIO_AC3,         AUDIO_FORMAT_AC3},
     { MEDIA_MIMETYPE_AUDIO_EAC3,        AUDIO_FORMAT_E_AC3},
+    { MEDIA_MIMETYPE_AUDIO_EAC3_JOC,    AUDIO_FORMAT_E_AC3_JOC},
     { MEDIA_MIMETYPE_AUDIO_AC4,         AUDIO_FORMAT_AC4},
     { MEDIA_MIMETYPE_AUDIO_FLAC,        AUDIO_FORMAT_FLAC},
     { MEDIA_MIMETYPE_AUDIO_ALAC,        AUDIO_FORMAT_ALAC },
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index c647f5f..81777f1 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -61,8 +61,5 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/codecs/aacdec/Android.bp b/media/libstagefright/codecs/aacdec/Android.bp
index 7352854..25628a2 100644
--- a/media/libstagefright/codecs/aacdec/Android.bp
+++ b/media/libstagefright/codecs/aacdec/Android.bp
@@ -25,9 +25,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: ["libFraunhoferAAC"],
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index 9342351..ec1151b 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -22,9 +22,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: ["libFraunhoferAAC"],
diff --git a/media/libstagefright/codecs/amrwbenc/Android.bp b/media/libstagefright/codecs/amrwbenc/Android.bp
index ebe08c6..b9d45c1 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/Android.bp
@@ -134,9 +134,6 @@
     cflags: ["-Werror"],
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
@@ -166,9 +163,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: ["libstagefright_amrwbenc"],
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
index 81b3f69..95f9494 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
@@ -23,8 +23,5 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index cf50a04..8a34845 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -34,9 +34,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     ldflags: ["-Wl,-Bsymbolic"],
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index cefe77c..6371828 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -28,9 +28,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     cflags: [
diff --git a/media/libstagefright/codecs/flac/dec/Android.bp b/media/libstagefright/codecs/flac/dec/Android.bp
index 9af086b..1674cb2 100644
--- a/media/libstagefright/codecs/flac/dec/Android.bp
+++ b/media/libstagefright/codecs/flac/dec/Android.bp
@@ -26,9 +26,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index 73f0dac..9b696da 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -18,9 +18,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/codecs/g711/dec/Android.bp b/media/libstagefright/codecs/g711/dec/Android.bp
index 3d97d8c..7097688 100644
--- a/media/libstagefright/codecs/g711/dec/Android.bp
+++ b/media/libstagefright/codecs/g711/dec/Android.bp
@@ -29,9 +29,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/gsm/dec/Android.bp b/media/libstagefright/codecs/gsm/dec/Android.bp
index 1c3208b..a973f70 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.bp
+++ b/media/libstagefright/codecs/gsm/dec/Android.bp
@@ -23,9 +23,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index 45920e6..60fc446 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -28,9 +28,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.bp b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
index ca70cc2..41141b1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.bp
@@ -60,9 +60,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -106,9 +103,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index 6be4036..d4f7d50 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -44,9 +44,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -92,9 +89,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
@@ -122,9 +116,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: ["libstagefright_m4vh263enc"],
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index 00f2dd3..71e1170 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -17,7 +17,6 @@
 #ifndef SOFT_MPEG4_ENCODER_H_
 #define SOFT_MPEG4_ENCODER_H_
 
-#include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/omx/SoftVideoEncoderOMXComponent.h>
 #include "mp4enc_api.h"
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 9fa9a4c..2154f84 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -59,9 +59,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     include_dirs: ["frameworks/av/media/libstagefright/include"],
@@ -106,9 +103,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
@@ -144,9 +138,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: [
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index e55c2e7..d644207 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -127,13 +127,13 @@
         {
             tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
             si->main_data_begin = (tmp << 18) >> 23;    /* 9 */
-            si->private_bits    = (tmp << 23) >> 27;    /* 5 */
+            si->private_bits    = (tmp << 27) >> 27;    /* 5 */
         }
         else
         {
             tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
             si->main_data_begin = (tmp << 20) >> 23;    /* 9 */
-            si->private_bits    = (tmp << 23) >> 29;    /* 3 */
+            si->private_bits    = (tmp << 29) >> 29;    /* 3 */
 
         }
 
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index cd83db0..c655544 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -34,9 +34,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/on2/dec/Android.bp b/media/libstagefright/codecs/on2/dec/Android.bp
index 8a9399a..174f183 100644
--- a/media/libstagefright/codecs/on2/dec/Android.bp
+++ b/media/libstagefright/codecs/on2/dec/Android.bp
@@ -31,9 +31,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index 3d9feeb..891a771 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -26,9 +26,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static_libs: ["libvpx"],
diff --git a/media/libstagefright/codecs/opus/dec/Android.bp b/media/libstagefright/codecs/opus/dec/Android.bp
index 43318f2..afe459d 100644
--- a/media/libstagefright/codecs/opus/dec/Android.bp
+++ b/media/libstagefright/codecs/opus/dec/Android.bp
@@ -30,9 +30,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/raw/Android.bp b/media/libstagefright/codecs/raw/Android.bp
index c8d7d00..f822445 100644
--- a/media/libstagefright/codecs/raw/Android.bp
+++ b/media/libstagefright/codecs/raw/Android.bp
@@ -22,9 +22,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/colorconversion/Android.bp b/media/libstagefright/colorconversion/Android.bp
index 16e9ded..ba57497 100644
--- a/media/libstagefright/colorconversion/Android.bp
+++ b/media/libstagefright/colorconversion/Android.bp
@@ -24,8 +24,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index e944224..7a67e55 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -31,8 +31,5 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 8d486cf..6bfab16 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -24,9 +24,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     static: {
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 861528e..dcf1ab8 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -79,8 +79,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index f93ae65..aba44bb 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -50,6 +50,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm";
 const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
 const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3";
+const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC = "audio/eac3-joc";
 const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
 const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
 const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 523378e..8edddcc 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -52,6 +52,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
 extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
 extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC;
 extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
 extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
 extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
diff --git a/media/libstagefright/http/Android.bp b/media/libstagefright/http/Android.bp
index 2e49fc4..8655caf 100644
--- a/media/libstagefright/http/Android.bp
+++ b/media/libstagefright/http/Android.bp
@@ -29,9 +29,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     product_variables: {
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index 2907751..78d410a 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -25,9 +25,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/id3/Android.bp b/media/libstagefright/id3/Android.bp
index b42c053..7151d07 100644
--- a/media/libstagefright/id3/Android.bp
+++ b/media/libstagefright/id3/Android.bp
@@ -16,9 +16,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -47,9 +44,6 @@
 
     sanitize: {
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 73f93d1..5dd1966 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -461,6 +461,8 @@
 
     status_t setupEAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
 
+    status_t setupAC4Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
+
     status_t selectAudioPortFormat(
             OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
 
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index a462ae7..704bfdd 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -135,6 +135,8 @@
 constexpr int32_t VP9Profile3 = 0x08;
 constexpr int32_t VP9Profile2HDR = 0x1000;
 constexpr int32_t VP9Profile3HDR = 0x2000;
+constexpr int32_t VP9Profile2HDR10Plus = 0x4000;
+constexpr int32_t VP9Profile3HDR10Plus = 0x8000;
 
 constexpr int32_t VP9Level1  = 0x1;
 constexpr int32_t VP9Level11 = 0x2;
@@ -155,6 +157,7 @@
 constexpr int32_t HEVCProfileMain10      = 0x02;
 constexpr int32_t HEVCProfileMainStill   = 0x04;
 constexpr int32_t HEVCProfileMain10HDR10 = 0x1000;
+constexpr int32_t HEVCProfileMain10HDR10Plus = 0x2000;
 
 constexpr int32_t HEVCMainTierLevel1  = 0x1;
 constexpr int32_t HEVCHighTierLevel1  = 0x2;
@@ -343,6 +346,7 @@
 constexpr char KEY_GRID_COLUMNS[] = "grid-cols";
 constexpr char KEY_GRID_ROWS[] = "grid-rows";
 constexpr char KEY_HDR_STATIC_INFO[] = "hdr-static-info";
+constexpr char KEY_HDR10_PLUS_INFO[] = "hdr10-plus-info";
 constexpr char KEY_HEIGHT[] = "height";
 constexpr char KEY_I_FRAME_INTERVAL[] = "i-frame-interval";
 constexpr char KEY_INTRA_REFRESH_PERIOD[] = "intra-refresh-period";
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractor.h b/media/libstagefright/include/media/stagefright/MediaExtractor.h
index 71343d5..6f3e57e 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractor.h
@@ -135,6 +135,22 @@
     CMediaExtractorV2 *plugin;
 };
 
+class MediaExtractorCUnwrapperV3 : public MediaExtractorCUnwrapper {
+public:
+    explicit MediaExtractorCUnwrapperV3(CMediaExtractorV3 *plugin);
+    virtual size_t countTracks();
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags = 0);
+    virtual status_t getMetaData(MetaDataBase& meta);
+    virtual const char * name();
+    virtual uint32_t flags() const;
+    virtual status_t setMediaCas(const uint8_t* casToken, size_t size);
+protected:
+    virtual ~MediaExtractorCUnwrapperV3();
+private:
+    CMediaExtractorV3 *plugin;
+};
+
 }  // namespace android
 
 #endif  // MEDIA_EXTRACTOR_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index ef9f7ed..84e01f3 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -35,17 +35,21 @@
             const sp<DataSource> &source, const char *mime = NULL);
     static void LoadPlugins(const ::std::string& apkPath);
     static status_t dump(int fd, const Vector<String16>& args);
+    static void SetLinkedLibraries(const std::string& linkedLibraries);
 
 private:
     static Mutex gPluginMutex;
     static std::shared_ptr<std::list<sp<ExtractorPlugin>>> gPlugins;
     static bool gPluginsRegistered;
     static bool gIgnoreVersion;
+    static std::string gLinkedLibraries;
 
     static void RegisterExtractorsInApk(
             const char *apkPath, std::list<sp<ExtractorPlugin>> &pluginList);
     static void RegisterExtractorsInSystem(
             const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
+    static void RegisterExtractorsInApex(
+            const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
     static void RegisterExtractor(
             const sp<ExtractorPlugin> &plugin, std::list<sp<ExtractorPlugin>> &pluginList);
 
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index 7e00eb8..e516cf1 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -25,9 +25,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     shared_libs: [
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 6250045..8a76de3 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -79,9 +79,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -115,9 +112,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
     cflags: ["-Wall", "-Werror"],
 }
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index c499c77..b187035 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -164,6 +164,8 @@
             "audio_decoder.ac3", "audio_encoder.ac3" },
         { MEDIA_MIMETYPE_AUDIO_EAC3,
             "audio_decoder.eac3", "audio_encoder.eac3" },
+        { MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+            "audio_decoder.eac3_joc", "audio_encoder.eac3_joc" },
         { MEDIA_MIMETYPE_AUDIO_AC4,
             "audio_decoder.ac4", "audio_encoder.ac4" },
         { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
diff --git a/media/libstagefright/rtsp/Android.bp b/media/libstagefright/rtsp/Android.bp
index d1767d3..9bc9c89 100644
--- a/media/libstagefright/rtsp/Android.bp
+++ b/media/libstagefright/rtsp/Android.bp
@@ -46,9 +46,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
@@ -104,8 +101,5 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
diff --git a/media/libstagefright/timedtext/Android.bp b/media/libstagefright/timedtext/Android.bp
index 7c51333..97e1ec6 100644
--- a/media/libstagefright/timedtext/Android.bp
+++ b/media/libstagefright/timedtext/Android.bp
@@ -14,9 +14,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     include_dirs: [
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 97e1452..64ecc2d 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -14,9 +14,6 @@
             "unsigned-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
     srcs: [
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index 5737ac2..b55dbb0 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -36,9 +36,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 
 }
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 992dc9a..5dbcd08 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -561,7 +561,7 @@
     return processedBytes == mPacketSize ? processedBytes : -1;
 }
 
-int MtpDataPacket::write(struct usb_request *request,
+int64_t MtpDataPacket::write(struct usb_request *request,
                          UrbPacketDivisionMode divisionMode,
                          int fd,
                          size_t payloadSize) {
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 1ddb821..138f7b0 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -117,7 +117,8 @@
     int                 write(struct usb_request *request, UrbPacketDivisionMode divisionMode);
     // Similar to previous write method but it reads the payload from |fd|. If |size| is larger than
     // MTP_BUFFER_SIZE, the data will be sent by multiple bulk transfer requests.
-    int                 write(struct usb_request *request, UrbPacketDivisionMode divisionMode,
+    // Return type (int64_t) is used to handle the case that the size can be larger than 2GB.
+    int64_t             write(struct usb_request *request, UrbPacketDivisionMode divisionMode,
                               int fd, size_t size);
 #endif
 
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 993797a..9665c58 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -516,7 +516,7 @@
     return (MtpObjectHandle)-1;
 }
 
-bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
+bool MtpDevice::sendObject(MtpObjectHandle handle, uint32_t size, int srcFD) {
     std::lock_guard<std::mutex> lg(mMutex);
 
     if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
@@ -529,7 +529,7 @@
     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
         mData.setOperationCode(mRequest.getOperationCode());
         mData.setTransactionID(mRequest.getTransactionID());
-        const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
+        const int64_t writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
         const MtpResponseCode ret = readResponse();
         return ret == MTP_RESPONSE_OK && writeResult > 0;
     }
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 8cf9e5e..01bc3db 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -104,7 +104,7 @@
     MtpObjectInfo*          getObjectInfo(MtpObjectHandle handle);
     void*                   getThumbnail(MtpObjectHandle handle, int& outLength);
     MtpObjectHandle         sendObjectInfo(MtpObjectInfo* info);
-    bool                    sendObject(MtpObjectHandle handle, int size, int srcFD);
+    bool                    sendObject(MtpObjectHandle handle, uint32_t size, int srcFD);
     bool                    deleteObject(MtpObjectHandle handle);
     MtpObjectHandle         getParent(MtpObjectHandle handle);
     MtpStorageID            getStorageID(MtpObjectHandle handle);
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 541ba3e..e355183 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -104,6 +104,7 @@
             enabled: false,
         },
     },
+    version_script: "libmediandk.map.txt",
 }
 
 llndk_library {
@@ -149,9 +150,6 @@
             "signed-integer-overflow",
         ],
         cfi: true,
-        diag: {
-            cfi: true,
-        },
     },
 }
 
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index bf9725c..200439c 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -320,6 +320,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_GRID_COLUMNS = "grid-cols";
 EXPORT const char* AMEDIAFORMAT_KEY_GRID_ROWS = "grid-rows";
 EXPORT const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO = "hdr-static-info";
+EXPORT const char* AMEDIAFORMAT_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
 EXPORT const char* AMEDIAFORMAT_KEY_HEIGHT = "height";
 EXPORT const char* AMEDIAFORMAT_KEY_ICC_PROFILE = "icc-profile";
 EXPORT const char* AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
@@ -327,6 +328,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_IS_AUTOSELECT = "is-autoselect";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_DEFAULT = "is-default";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
+EXPORT const char* AMEDIAFORMAT_KEY_IS_SYNC_FRAME = "is-sync-frame";
 EXPORT const char* AMEDIAFORMAT_KEY_I_FRAME_INTERVAL = "i-frame-interval";
 EXPORT const char* AMEDIAFORMAT_KEY_LANGUAGE = "language";
 EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency";
diff --git a/media/ndk/include/media/NdkMediaCodec.h b/media/ndk/include/media/NdkMediaCodec.h
index 9dc120d..b3ee853 100644
--- a/media/ndk/include/media/NdkMediaCodec.h
+++ b/media/ndk/include/media/NdkMediaCodec.h
@@ -241,12 +241,6 @@
 AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*) __INTRODUCED_IN(21);
 
 /**
- * Get format of the buffer. The specified buffer index must have been previously obtained from
- * dequeueOutputBuffer.
- */
-AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec*, size_t index) __INTRODUCED_IN(21);
-
-/**
  * If you are done with a buffer, use this call to return the buffer to
  * the codec. If you previously specified a surface when configuring this
  * video decoder you can optionally render the buffer.
@@ -353,6 +347,12 @@
 #if __ANDROID_API__ >= 28
 
 /**
+ * Get format of the buffer. The specified buffer index must have been previously obtained from
+ * dequeueOutputBuffer.
+ */
+AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec*, size_t index) __INTRODUCED_IN(28);
+
+/**
  * Get the component name. If the codec was created by createDecoderByType
  * or createEncoderByType, what component is chosen is not known beforehand.
  * Caller shall call AMediaCodec_releaseName to free the returned pointer.
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 658cbac..13d9135 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -184,9 +184,6 @@
 extern const char* AMEDIAFORMAT_KEY_AUTHOR __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_BITS_PER_SAMPLE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_RANGE __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_STANDARD __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE __INTRODUCED_IN(29);
@@ -207,8 +204,8 @@
 extern const char* AMEDIAFORMAT_KEY_EXIF_SIZE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_FRAME_COUNT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_ICC_PROFILE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_IS_SYNC_FRAME __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LOCATION __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LOOP __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29);
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index d3bdbae..3567899 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -35,64 +35,110 @@
     AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT; # var introduced=28
     AMEDIAFORMAT_KEY_AAC_PROFILE; # var introduced=21
     AMEDIAFORMAT_KEY_AAC_SBR_MODE; # var introduced=28
+    AMEDIAFORMAT_KEY_ALBUM; # var introduced=29
+    AMEDIAFORMAT_KEY_ALBUMART; # var introduced=29
+    AMEDIAFORMAT_KEY_ALBUMARTIST; # var introduced=29
+    AMEDIAFORMAT_KEY_ARTIST; # var introduced=29
+    AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO; # var introduced=29
     AMEDIAFORMAT_KEY_AUDIO_SESSION_ID; # var introduced=28
+    AMEDIAFORMAT_KEY_AUTHOR; # var introduced=29
     AMEDIAFORMAT_KEY_BITRATE_MODE; # var introduced=28
     AMEDIAFORMAT_KEY_BIT_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_BITS_PER_SAMPLE; # var introduced=29
     AMEDIAFORMAT_KEY_CAPTURE_RATE; # var introduced=28
+    AMEDIAFORMAT_KEY_CDTRACKNUMBER; # var introduced=29
     AMEDIAFORMAT_KEY_CHANNEL_COUNT; # var introduced=21
     AMEDIAFORMAT_KEY_CHANNEL_MASK; # var introduced=21
     AMEDIAFORMAT_KEY_COLOR_FORMAT; # var introduced=21
     AMEDIAFORMAT_KEY_COLOR_RANGE; # var introduced=28
     AMEDIAFORMAT_KEY_COLOR_STANDARD; # var introduced=28
     AMEDIAFORMAT_KEY_COLOR_TRANSFER; # var introduced=28
+    AMEDIAFORMAT_KEY_COMPILATION; # var introduced=29
     AMEDIAFORMAT_KEY_COMPLEXITY; # var introduced=28
+    AMEDIAFORMAT_KEY_COMPOSER; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_IV; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_KEY; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_MODE; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK; # var introduced=29
     AMEDIAFORMAT_KEY_CSD; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_0; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_1; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_2; # var introduced=28
+    AMEDIAFORMAT_KEY_CSD_AVC; # var introduced=29
+    AMEDIAFORMAT_KEY_CSD_HEVC; # var introduced=29
+    AMEDIAFORMAT_KEY_D263; # var introduced=29
+    AMEDIAFORMAT_KEY_DATE; # var introduced=29
+    AMEDIAFORMAT_KEY_DISCNUMBER; # var introduced=29
     AMEDIAFORMAT_KEY_DISPLAY_CROP; # var introduced=28
     AMEDIAFORMAT_KEY_DISPLAY_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_DISPLAY_WIDTH; # var introduced=28
     AMEDIAFORMAT_KEY_DURATION; # var introduced=21
+    AMEDIAFORMAT_KEY_ENCODER_DELAY; # var introduced=29
+    AMEDIAFORMAT_KEY_ENCODER_PADDING; # var introduced=29
+    AMEDIAFORMAT_KEY_ESDS; # var introduced=29
+    AMEDIAFORMAT_KEY_EXIF_OFFSET; # var introduced=29
+    AMEDIAFORMAT_KEY_EXIF_SIZE; # var introduced=29
+    AMEDIAFORMAT_KEY_FRAME_COUNT; # var introduced=29
     AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL; # var introduced=21
     AMEDIAFORMAT_KEY_FRAME_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_GENRE; # var introduced=29
     AMEDIAFORMAT_KEY_GRID_COLUMNS; # var introduced=28
     AMEDIAFORMAT_KEY_GRID_ROWS; # var introduced=28
     AMEDIAFORMAT_KEY_HDR_STATIC_INFO; # var introduced=28
     AMEDIAFORMAT_KEY_HEIGHT; # var introduced=21
+    AMEDIAFORMAT_KEY_ICC_PROFILE; # var introduced=29
     AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD; # var introduced=28
     AMEDIAFORMAT_KEY_IS_ADTS; # var introduced=21
     AMEDIAFORMAT_KEY_IS_AUTOSELECT; # var introduced=21
     AMEDIAFORMAT_KEY_IS_DEFAULT; # var introduced=21
     AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE; # var introduced=21
+    AMEDIAFORMAT_KEY_IS_SYNC_FRAME; # var introduced=29
     AMEDIAFORMAT_KEY_I_FRAME_INTERVAL; # var introduced=21
     AMEDIAFORMAT_KEY_LANGUAGE; # var introduced=21
     AMEDIAFORMAT_KEY_LATENCY; # var introduced=28
     AMEDIAFORMAT_KEY_LEVEL; # var introduced=28
+    AMEDIAFORMAT_KEY_LOCATION; # var introduced=29
+    AMEDIAFORMAT_KEY_LOOP; # var introduced=29
+    AMEDIAFORMAT_KEY_LYRICIST; # var introduced=29
+    AMEDIAFORMAT_KEY_MAX_BIT_RATE; # var introduced=29
     AMEDIAFORMAT_KEY_MAX_HEIGHT; # var introduced=21
     AMEDIAFORMAT_KEY_MAX_INPUT_SIZE; # var introduced=21
     AMEDIAFORMAT_KEY_MAX_WIDTH; # var introduced=21
     AMEDIAFORMAT_KEY_MIME; # var introduced=21
     AMEDIAFORMAT_KEY_MPEG_USER_DATA; # var introduced=28
+    AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER; # var introduced=29
     AMEDIAFORMAT_KEY_OPERATING_RATE; # var introduced=28
+    AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN; # var introduced=29
     AMEDIAFORMAT_KEY_PCM_ENCODING; # var introduced=28
     AMEDIAFORMAT_KEY_PRIORITY; # var introduced=28
     AMEDIAFORMAT_KEY_PROFILE; # var introduced=28
+    AMEDIAFORMAT_KEY_PSSH; # var introduced=29
     AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP; # var introduced=21
     AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER; # var introduced=21
     AMEDIAFORMAT_KEY_ROTATION; # var introduced=28
     AMEDIAFORMAT_KEY_SAMPLE_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_SAR_HEIGHT; # var introduced=29
+    AMEDIAFORMAT_KEY_SAR_WIDTH; # var introduced=29
     AMEDIAFORMAT_KEY_SEI; # var introduced=28
     AMEDIAFORMAT_KEY_SLICE_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_STRIDE; # var introduced=21
+    AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT; # var introduced=29
     AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID; # var introduced=28
     AMEDIAFORMAT_KEY_TEMPORAL_LAYERING; # var introduced=28
+    AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_TIME; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH; # var introduced=29
+    AMEDIAFORMAT_KEY_TITLE; # var introduced=28
     AMEDIAFORMAT_KEY_TILE_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_TILE_WIDTH; # var introduced=28
     AMEDIAFORMAT_KEY_TIME_US; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_INDEX; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
     AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
+    AMEDIAFORMAT_KEY_YEAR; # var introduced=29
     AMediaCodecActionCode_isRecoverable; # introduced=28
     AMediaCodecActionCode_isTransient; # introduced=28
     AMediaCodecCryptoInfo_delete;
@@ -112,6 +158,7 @@
     AMediaCodec_dequeueInputBuffer;
     AMediaCodec_dequeueOutputBuffer;
     AMediaCodec_flush;
+    AMediaCodec_getBufferFormat; # introduced=28
     AMediaCodec_getInputBuffer;
     AMediaCodec_getInputFormat; # introduced=28
     AMediaCodec_getName; # introduced=28
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaController.java b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
index a8e77c7..60f74ab 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaController.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
@@ -149,12 +149,9 @@
         if (keyEvent == null) {
             throw new IllegalArgumentException("KeyEvent may not be null");
         }
-        //TODO(b/119789707): Resolve hidden API usage: KeyEvent#isMediaKey
-        /*
-        if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
+        if (!KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
             return false;
         }
-        */
         try {
             //TODO(b/119748678): Resolve mContext.getOpPackageName() through this file.
             // Temporarilly it's replaced with "mContext.getOpPackageName()" for compiling.
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index b40e3b0..04dc0b8 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -1072,12 +1072,8 @@
 
         private static RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid,
                 ISessionControllerCallback caller) {
-            //TODO(b/119752205): Resolve hidden API usage. 4-param constructor of RemoteUserInfo
-            /*
             return new RemoteUserInfo(packageName, pid, uid,
                     caller != null ? caller.asBinder() : null);
-            */
-            return new RemoteUserInfo(packageName, pid, uid);
         }
 
         @Override
diff --git a/packages/MediaComponents/apex/java/android/service/media/MediaBrowserService.java b/packages/MediaComponents/apex/java/android/service/media/MediaBrowserService.java
index 2f2fbaf..fa7696e 100644
--- a/packages/MediaComponents/apex/java/android/service/media/MediaBrowserService.java
+++ b/packages/MediaComponents/apex/java/android/service/media/MediaBrowserService.java
@@ -544,12 +544,8 @@
             throw new IllegalStateException("This should be called inside of onGetRoot or"
                     + " onLoadChildren or onLoadItem methods");
         }
-        //TODO(b/119752205): Resolve hidden API usage. 4-param constructor of RemoteUserInfo
-        /*
         return new RemoteUserInfo(mCurConnection.pkg, mCurConnection.pid, mCurConnection.uid,
                 mCurConnection.callbacks.asBinder());
-        */
-        return new RemoteUserInfo(mCurConnection.pkg, mCurConnection.pid, mCurConnection.uid);
     }
 
     /**
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 06975ac..26f76c0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -746,7 +746,7 @@
         output.afFrameCount = thread->frameCount();
         output.afSampleRate = thread->sampleRate();
         output.afLatencyMs = thread->latency();
-        output.trackId = track == nullptr ? -1 : track->id();
+        output.portId = portId;
 
         // move effect chain to this output thread if an effect on same session was waiting
         // for a track to be created
@@ -1766,7 +1766,7 @@
 
     output.cblk = recordTrack->getCblk();
     output.buffers = recordTrack->getBuffers();
-    output.trackId = recordTrack->id();
+    output.portId = portId;
 
     // return handle to client
     recordHandle = new RecordHandle(recordTrack);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 46e40c7..3dae1e9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7367,8 +7367,7 @@
         status_t status = NO_ERROR;
         if (recordTrack->isExternalTrack()) {
             mLock.unlock();
-            bool silenced;
-            status = AudioSystem::startInput(recordTrack->portId(), &silenced);
+            status = AudioSystem::startInput(recordTrack->portId());
             mLock.lock();
             if (recordTrack->isInvalid()) {
                 recordTrack->clearSyncStartEvent();
@@ -7396,7 +7395,6 @@
                 recordTrack->clearSyncStartEvent();
                 return status;
             }
-            recordTrack->setSilenced(silenced);
         }
         // Catch up with current buffer indices if thread is already running.
         // This is what makes a new client discard all buffered data.  If the track's mRsmpInFront
@@ -7562,7 +7560,7 @@
         (void)input->stream->dump(fd);
     }
 
-    const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, input->flags)
+    const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
             ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
     if (latencyMs != 0.) {
         dprintf(fd, "  NormalRecord latency ms: %.2lf\n", latencyMs);
@@ -8346,11 +8344,10 @@
         return BAD_VALUE;
     }
 
-    bool silenced = false;
     if (isOutput()) {
         ret = AudioSystem::startOutput(portId);
     } else {
-        ret = AudioSystem::startInput(portId, &silenced);
+        ret = AudioSystem::startInput(portId);
     }
 
     Mutex::Autolock _l(mLock);
@@ -8371,21 +8368,21 @@
         return PERMISSION_DENIED;
     }
 
-    if (isOutput()) {
-        // force volume update when a new track is added
-        mHalVolFloat = -1.0f;
-    } else if (!silenced) {
-        for (const sp<MmapTrack> &track : mActiveTracks) {
-            if (track->isSilenced_l() && track->uid() != client.clientUid)
-                track->invalidate();
-        }
-    }
-
     // Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
     sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
                                         isOutput(), client.clientUid, client.clientPid, portId);
 
-    track->setSilenced_l(silenced);
+    if (isOutput()) {
+        // force volume update when a new track is added
+        mHalVolFloat = -1.0f;
+    } else if (!track->isSilenced_l()) {
+        for (const sp<MmapTrack> &t : mActiveTracks) {
+            if (t->isSilenced_l() && t->uid() != client.clientUid)
+                t->invalidate();
+        }
+    }
+
+
     mActiveTracks.add(track);
     sp<EffectChain> chain = getEffectChain_l(mSessionId);
     if (chain != 0) {
@@ -9146,7 +9143,13 @@
 
 status_t AudioFlinger::MmapCaptureThread::exitStandby()
 {
-    mInput->stream->setGain(1.0f);
+    {
+        // mInput might have been cleared by clearInput()
+        Mutex::Autolock _l(mLock);
+        if (mInput != nullptr && mInput->stream != nullptr) {
+            mInput->stream->setGain(1.0f);
+        }
+    }
     return MmapThread::exitStandby();
 }
 
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index dd81c71..9a7f1f1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -502,7 +502,7 @@
 
 void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Type     Id Active Client Session S  Flags "
+    result.appendFormat("Type     Id Active Client Session Port Id S  Flags "
                         "  Format Chn mask  SRate "
                         "ST Usg CT "
                         " G db  L dB  R dB  VS dB "
@@ -588,7 +588,7 @@
             ? 'r' /* buffer reduced */: bufferSizeInFrames > mFrameCount
                     ? 'e' /* error */ : ' ' /* identical */;
 
-    result.appendFormat("%7s %6u %7u %2s 0x%03X "
+    result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
                         "%08X %08X %6u "
                         "%2u %3x %2x "
                         "%5.2g %5.2g %5.2g %5.2g%c "
@@ -596,6 +596,7 @@
             active ? "yes" : "no",
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
+            mPortId,
             getTrackStateString(),
             mCblk->mFlags,
 
@@ -1886,7 +1887,7 @@
 
 void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Active     Id Client Session S  Flags  "
+    result.appendFormat("Active     Id Client Session Port Id  S  Flags  "
                         " Format Chn mask  SRate Source  "
                         " Server FrmCnt FrmRdy Sil%s\n",
                         isServerLatencySupported() ? "   Latency" : "");
@@ -1894,7 +1895,7 @@
 
 void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active)
 {
-    result.appendFormat("%c%5s %6d %6u %7u %2s 0x%03X "
+    result.appendFormat("%c%5s %6d %6u %7u %7u  %2s 0x%03X "
             "%08X %08X %6u %6X "
             "%08X %6zu %6zu %3c",
             isFastTrack() ? 'F' : ' ',
@@ -1902,6 +1903,7 @@
             mId,
             (mClient == 0) ? getpid() : mClient->pid(),
             mSessionId,
+            mPortId,
             getTrackStateString(),
             mCblk->mFlags,
 
@@ -2142,15 +2144,16 @@
 
 void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
 {
-    result.appendFormat("Client Session   Format Chn mask  SRate Flags %s\n",
+    result.appendFormat("Client Session Port Id  Format Chn mask  SRate Flags %s\n",
                         isOut() ? "Usg CT": "Source");
 }
 
 void AudioFlinger::MmapThread::MmapTrack::appendDump(String8& result, bool active __unused)
 {
-    result.appendFormat("%6u %7u %08X %08X %6u 0x%03X ",
+    result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
             mPid,
             mSessionId,
+            mPortId,
             mFormat,
             mChannelMask,
             mSampleRate,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 7c7fe85..ea6389c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -65,20 +65,6 @@
         API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
     } input_type_t;
 
-    enum {
-        API_INPUT_CONCURRENCY_NONE = 0,
-        API_INPUT_CONCURRENCY_CALL = (1 << 0),      // Concurrency with a call
-        API_INPUT_CONCURRENCY_CAPTURE = (1 << 1),   // Concurrency with another capture
-        API_INPUT_CONCURRENCY_HOTWORD = (1 << 2),   // Concurrency with a hotword
-        API_INPUT_CONCURRENCY_PREEMPT = (1 << 3),   // pre-empted someone
-                // NB: preempt is marked on a successful return, others are on failing calls
-        API_INPUT_CONCURRENCY_LAST = (1 << 4),
-
-        API_INPUT_CONCURRENCY_ALL = (API_INPUT_CONCURRENCY_LAST - 1),
-    };
-
-    typedef uint32_t concurrency_type__mask_t;
-
 public:
     virtual ~AudioPolicyInterface() {}
     //
@@ -141,9 +127,7 @@
                                      input_type_t *inputType,
                                      audio_port_handle_t *portId) = 0;
     // indicates to the audio policy manager that the input starts being used.
-    virtual status_t startInput(audio_port_handle_t portId,
-                                bool silenced,
-                                concurrency_type__mask_t *concurrency) = 0;
+    virtual status_t startInput(audio_port_handle_t portId) = 0;
     // indicates to the audio policy manager that the input stops being used.
     virtual status_t stopInput(audio_port_handle_t portId) = 0;
     // releases the input.
@@ -197,6 +181,8 @@
     virtual status_t    dump(int fd) = 0;
 
     virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0;
+    virtual bool isDirectOutputSupported(const audio_config_base_t& config,
+                                         const audio_attributes_t& attributes) = 0;
 
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 9bd68e1..30b0044 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -32,14 +32,6 @@
 #define MAX_MIXER_CHANNEL_COUNT FCC_8
 
 /**
- * A device mask for all audio input devices that are considered "virtual" when evaluating
- * active inputs in getActiveInputs()
- */
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|\
-        AUDIO_DEVICE_IN_BUS|AUDIO_DEVICE_IN_FM_TUNER)
-
-
-/**
  * A device mask for all audio input and output devices where matching inputs/outputs on device
  * type alone is not enough: the address must match too
  */
@@ -68,23 +60,6 @@
 }
 
 /**
- * Check if the input device given is considered as a virtual device.
- *
- * @param[in] device to consider
- *
- * @return true if the device is a virtual one, false otherwise.
- */
-static inline bool is_virtual_input_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
-            return true;
-    }
-    return false;
-}
-
-/**
  * Check whether the device type is one
  * where addresses are used to distinguish between one connected device and another
  *
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 6e4c044..9f8b8c0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -58,9 +58,8 @@
     void clearPreemptedSessions();
     bool isActive() const { return mGlobalActiveCount > 0; }
     bool isSourceActive(audio_source_t source) const;
-    audio_source_t inputSource(bool activeOnly = false) const;
+    audio_source_t source() const;
     bool isSoundTrigger() const;
-    audio_source_t getHighestPrioritySource(bool activeOnly) const;
     void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
     int32_t activeCount() { return mGlobalActiveCount; }
 
@@ -121,7 +120,7 @@
      * Only considers inputs from physical devices (e.g. main mic, headset mic) when
      * ignoreVirtualInputs is true.
      */
-    Vector<sp <AudioInputDescriptor> > getActiveInputs(bool ignoreVirtualInputs = true);
+    Vector<sp <AudioInputDescriptor> > getActiveInputs();
 
     audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index d1a0f9b..5099ebb 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -176,7 +176,8 @@
                     AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
                     AUDIO_FORMAT_AAC_XHE}},
             {AUDIO_FORMAT_DOLBY_TRUEHD, {}},
-            {AUDIO_FORMAT_E_AC3_JOC, {}}};
+            {AUDIO_FORMAT_E_AC3_JOC, {}},
+            {AUDIO_FORMAT_AC4, {}}};
     }
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 030bf4b..986d109 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include <system/audio.h>
+#include <system/audio_policy.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -106,7 +107,7 @@
                         audio_port_handle_t preferredDeviceId,
                         audio_source_t source, audio_input_flags_t flags, bool isSoundTrigger) :
         ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId),
-        mSource(source), mFlags(flags), mIsSoundTrigger(isSoundTrigger), mSilenced(false) {}
+        mSource(source), mFlags(flags), mIsSoundTrigger(isSoundTrigger), mAppState(APP_STATE_IDLE) {}
     ~RecordClientDescriptor() override = default;
 
     using ClientDescriptor::dump;
@@ -115,14 +116,16 @@
     audio_source_t source() const { return mSource; }
     audio_input_flags_t flags() const { return mFlags; }
     bool isSoundTrigger() const { return mIsSoundTrigger; }
-    void setSilenced(bool silenced) { mSilenced = silenced; }
-    bool isSilenced() const { return mSilenced; }
+    void setAppState(app_state_t appState) { mAppState = appState; }
+    app_state_t appState() { return mAppState; }
+    bool isSilenced() const { return mAppState == APP_STATE_IDLE; }
 
 private:
     const audio_source_t mSource;
     const audio_input_flags_t mFlags;
     const bool mIsSoundTrigger;
-          bool mSilenced;
+          app_state_t mAppState;
+
 };
 
 class SourceClientDescriptor: public TrackClientDescriptor
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 83fb10c..6f99bf3 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -31,6 +31,8 @@
 public:
      // Note that empty name refers by convention to a generic device.
     explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
+    DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
+            const String8 &tagName = String8(""));
 
     virtual ~DeviceDescriptor() {}
 
@@ -38,6 +40,8 @@
 
     audio_devices_t type() const { return mDeviceType; }
 
+    const FormatVector& encodedFormats() const { return mEncodedFormats; }
+
     bool equals(const sp<DeviceDescriptor>& other) const;
 
     // AudioPortConfig
@@ -59,6 +63,7 @@
 private:
     String8 mTagName; // Unique human readable identifier for a device port found in conf file.
     audio_devices_t     mDeviceType;
+    FormatVector        mEncodedFormats;
     audio_port_handle_t mId;
 
 friend class DeviceVector;
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index eb32959..8ff8238 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -35,7 +35,7 @@
 public:
     IOProfile(const String8 &name, audio_port_role_t role)
         : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
-          maxOpenCount((role == AUDIO_PORT_ROLE_SOURCE) ? 1 : 0),
+          maxOpenCount(1),
           curOpenCount(0),
           maxActiveCount(1),
           curActiveCount(0) {}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 1f29874..559274f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -53,9 +53,32 @@
     return mId;
 }
 
-audio_source_t AudioInputDescriptor::inputSource(bool activeOnly) const
+audio_source_t AudioInputDescriptor::source() const
 {
-    return getHighestPrioritySource(activeOnly);
+    audio_source_t source = AUDIO_SOURCE_DEFAULT;
+
+    for (bool activeOnly : { true, false }) {
+        int32_t topPriority = -1;
+        app_state_t topState = APP_STATE_IDLE;
+        for (const auto &client : getClientIterable()) {
+            if (activeOnly && !client->active()) {
+                continue;
+            }
+            app_state_t curState = client->appState();
+            if (curState >= topState) {
+                int32_t curPriority = source_priority(client->source());
+                if (curPriority > topPriority) {
+                    source = client->source();
+                    topPriority = curPriority;
+                }
+                topState = curState;
+            }
+        }
+        if (source != AUDIO_SOURCE_DEFAULT) {
+            break;
+        }
+    }
+    return source;
 }
 
 void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -76,7 +99,7 @@
     dstConfig->type = AUDIO_PORT_TYPE_MIX;
     dstConfig->ext.mix.hw_module = getModuleHandle();
     dstConfig->ext.mix.handle = mIoHandle;
-    dstConfig->ext.mix.usecase.source = inputSource();
+    dstConfig->ext.mix.usecase.source = source();
 }
 
 void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
@@ -125,24 +148,6 @@
     return false;
 }
 
-audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
-{
-    audio_source_t source = AUDIO_SOURCE_DEFAULT;
-    int32_t priority = -1;
-
-    for (const auto &client : getClientIterable()) {
-        if (activeOnly && !client->active() ) {
-            continue;
-        }
-        int32_t curPriority = source_priority(client->source());
-        if (curPriority > priority) {
-            priority = curPriority;
-            source = client->source();
-        }
-    }
-    return source;
-}
-
 bool AudioInputDescriptor::isSoundTrigger() const {
     // sound trigger and non sound trigger clients are not mixed on a given input
     // so check only first client
@@ -224,7 +229,7 @@
 
 status_t AudioInputDescriptor::start()
 {
-    if (mGlobalActiveCount == 1) {
+    if (!isActive()) {
         if (!mProfile->canStartNewIo()) {
             ALOGI("%s mProfile->curActiveCount %d", __func__, mProfile->curActiveCount);
             return INVALID_OPERATION;
@@ -388,15 +393,13 @@
     return count;
 }
 
-Vector<sp <AudioInputDescriptor> > AudioInputCollection::getActiveInputs(bool ignoreVirtualInputs)
+Vector<sp <AudioInputDescriptor> > AudioInputCollection::getActiveInputs()
 {
     Vector<sp <AudioInputDescriptor> > activeInputs;
 
     for (size_t i = 0; i < size(); i++) {
         const sp<AudioInputDescriptor>  inputDescriptor = valueAt(i);
-        if ((inputDescriptor->isActive())
-                && (!ignoreVirtualInputs ||
-                    !is_virtual_input_device(inputDescriptor->mDevice))) {
+        if (inputDescriptor->isActive()) {
             activeInputs.add(inputDescriptor);
         }
     }
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index a9f7220..9e5f944 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -26,14 +26,25 @@
 namespace android {
 
 DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
+        DeviceDescriptor(type, FormatVector{}, tagName)
+{
+}
+
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
+        const String8 &tagName) :
     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                              AUDIO_PORT_ROLE_SOURCE),
-    mAddress(""), mTagName(tagName), mDeviceType(type), mId(0)
+    mAddress(""), mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats), mId(0)
 {
     if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
         mAddress = String8("0");
     }
+    /* FIXME: read from APM config file */
+    if (type == AUDIO_DEVICE_OUT_HDMI) {
+        mEncodedFormats.add(AUDIO_FORMAT_AC3);
+        mEncodedFormats.add(AUDIO_FORMAT_IEC61937);
+    }
 }
 
 audio_port_handle_t DeviceDescriptor::getId() const
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index 1d037c3..b5ecbf9 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -198,7 +198,7 @@
 
     <!-- End of Volume section -->
 
-    <?disabledUntilHalV4_1
+    <?disabledUntilHalV5_0
     <!-- Surround configuration -->
 
     <surroundSound>
@@ -214,6 +214,7 @@
         <format name="AUDIO_FORMAT_DTS" />
         <format name="AUDIO_FORMAT_DTS_HD" />
         <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
+        <format name="AUDIO_FORMAT_AC4" />
       </formats>
     </surroundSound>
 
diff --git a/services/audiopolicy/config/msd_audio_policy_configuration.xml b/services/audiopolicy/config/msd_audio_policy_configuration.xml
index a811f5e..db17bc6 100644
--- a/services/audiopolicy/config/msd_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/msd_audio_policy_configuration.xml
@@ -32,6 +32,9 @@
             <profile name="" format="AUDIO_FORMAT_E_AC3"
                      samplingRates="32000,44100,48000"
                      channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+            <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
+                     samplingRates="32000,44100,48000"
+                     channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
             <profile name="" format="AUDIO_FORMAT_AC4"
                      samplingRates="32000,44100,48000"
                      channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
@@ -50,6 +53,18 @@
        <devicePort tagName="MS12 Input" type="AUDIO_DEVICE_OUT_BUS"  role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+           <profile name="" format="AUDIO_FORMAT_AC3"
+                    samplingRates="32000,44100,48000"
+                    channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1"/>
+           <profile name="" format="AUDIO_FORMAT_E_AC3"
+                    samplingRates="32000,44100,48000"
+                    channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+            <profile name="" format="AUDIO_FORMAT_E_AC3_JOC"
+                     samplingRates="32000,44100,48000"
+                     channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
+           <profile name="" format="AUDIO_FORMAT_AC4"
+                    samplingRates="32000,44100,48000"
+                    channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
        </devicePort>
        <devicePort tagName="MS12 Output" type="AUDIO_DEVICE_IN_BUS"  role="source">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 6a5a646..2a63493 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -36,6 +36,7 @@
 
 #include <inttypes.h>
 #include <math.h>
+#include <unordered_set>
 #include <vector>
 
 #include <AudioPolicyManagerInterface.h>
@@ -216,7 +217,8 @@
             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
             updateCallRouting(newDevice);
         }
-        const audio_devices_t msdOutDevice = getMsdAudioOutDeviceTypes();
+        const audio_devices_t msdOutDevice = getModuleDeviceTypes(
+                mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);
         for (size_t i = 0; i < mOutputs.size(); i++) {
             sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
             if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
@@ -525,6 +527,24 @@
     return deviceList.itemAt(0);
 }
 
+audio_devices_t AudioPolicyManager::getModuleDeviceTypes(
+        const DeviceVector& devices, const char *moduleId) const {
+    sp<HwModule> mod = mHwModules.getModuleFromName(moduleId);
+    return mod != 0 ? devices.getDeviceTypesFromHwModule(mod->getHandle()) : AUDIO_DEVICE_NONE;
+}
+
+bool AudioPolicyManager::isDeviceOfModule(
+        const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
+    sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
+    if (module != 0) {
+        return mAvailableOutputDevices.getDevicesFromHwModule(module->getHandle())
+                .indexOf(devDesc) != NAME_NOT_FOUND
+                || mAvailableInputDevices.getDevicesFromHwModule(module->getHandle())
+                .indexOf(devDesc) != NAME_NOT_FOUND;
+    }
+    return false;
+}
+
 void AudioPolicyManager::setPhoneState(audio_mode_t state)
 {
     ALOGV("setPhoneState() state %d", state);
@@ -692,22 +712,25 @@
     ALOGV("setSystemProperty() property %s, value %s", property, value);
 }
 
-// Find a direct output profile compatible with the parameters passed, even if the input flags do
-// not explicitly request a direct output
-sp<IOProfile> AudioPolicyManager::getProfileForDirectOutput(
-                                                               audio_devices_t device,
-                                                               uint32_t samplingRate,
-                                                               audio_format_t format,
-                                                               audio_channel_mask_t channelMask,
-                                                               audio_output_flags_t flags)
+// Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict
+// search to profiles for direct outputs.
+sp<IOProfile> AudioPolicyManager::getProfileForOutput(
+                                                   audio_devices_t device,
+                                                   uint32_t samplingRate,
+                                                   audio_format_t format,
+                                                   audio_channel_mask_t channelMask,
+                                                   audio_output_flags_t flags,
+                                                   bool directOnly)
 {
-    // only retain flags that will drive the direct output profile selection
-    // if explicitly requested
-    static const uint32_t kRelevantFlags =
-            (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
-             AUDIO_OUTPUT_FLAG_VOIP_RX);
-    flags =
-        (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
+    if (directOnly) {
+        // only retain flags that will drive the direct output profile selection
+        // if explicitly requested
+        static const uint32_t kRelevantFlags =
+                (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+                 AUDIO_OUTPUT_FLAG_VOIP_RX);
+        flags =
+            (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
+    }
 
     sp<IOProfile> profile;
 
@@ -724,7 +747,9 @@
             if ((mAvailableOutputDevices.types() & curProfile->getSupportedDevicesType()) == 0) {
                 continue;
             }
-            // if several profiles are compatible, give priority to one with offload capability
+            if (!directOnly) return curProfile;
+            // when searching for direct outputs, if several profiles are compatible, give priority
+            // to one with offload capability
             if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
                 continue;
             }
@@ -770,7 +795,8 @@
     routing_strategy strategy;
     audio_devices_t device;
     const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
-    audio_devices_t msdDevice = getMsdAudioOutDeviceTypes();
+    audio_devices_t msdDevice =
+            getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);
 
     // The supplied portId must be AUDIO_PORT_HANDLE_NONE
     if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -959,11 +985,12 @@
 
     if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
             !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
-        profile = getProfileForDirectOutput(device,
-                                           config->sample_rate,
-                                           config->format,
-                                           config->channel_mask,
-                                           (audio_output_flags_t)*flags);
+        profile = getProfileForOutput(device,
+                                   config->sample_rate,
+                                   config->format,
+                                   config->channel_mask,
+                                   (audio_output_flags_t)*flags,
+                                   true /* directOnly */);
     }
 
     if (profile != 0) {
@@ -1083,14 +1110,6 @@
     return 0;
 }
 
-audio_devices_t AudioPolicyManager::getMsdAudioOutDeviceTypes() const {
-    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
-    if (msdModule != 0) {
-        return mAvailableOutputDevices.getDeviceTypesFromHwModule(msdModule->getHandle());
-    }
-    return AUDIO_DEVICE_NONE;
-}
-
 const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
     AudioPatchCollection msdPatches;
     sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
@@ -1876,7 +1895,38 @@
     }
 
     if (!profile->canOpenNewIo()) {
-        return AUDIO_IO_HANDLE_NONE;
+        for (size_t i = 0; i < mInputs.size(); ) {
+            sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
+            if (desc->mProfile != profile) {
+                continue;
+            }
+            // if sound trigger, reuse input if used by other sound trigger on same session
+            // else
+            //    reuse input if active client app is not in IDLE state
+            //
+            RecordClientVector clients = desc->clientsList();
+            bool doClose = false;
+            for (const auto& client : clients) {
+                if (isSoundTrigger != client->isSoundTrigger()) {
+                    continue;
+                }
+                if (client->isSoundTrigger()) {
+                    if (session == client->session()) {
+                        return desc->mIoHandle;
+                    }
+                    continue;
+                }
+                if (client->active() && client->appState() != APP_STATE_IDLE) {
+                    return desc->mIoHandle;
+                }
+                doClose = true;
+            }
+            if (doClose) {
+                closeInput(desc->mIoHandle);
+            } else {
+                i++;
+            }
+        }
     }
 
     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface);
@@ -1917,55 +1967,8 @@
     return input;
 }
 
-//static
-bool AudioPolicyManager::isConcurrentSource(audio_source_t source)
+status_t AudioPolicyManager::startInput(audio_port_handle_t portId)
 {
-    return (source == AUDIO_SOURCE_HOTWORD) ||
-            (source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
-            (source == AUDIO_SOURCE_FM_TUNER);
-}
-
-// FIXME: remove when concurrent capture is ready. This is a hack to work around bug b/63083537.
-bool AudioPolicyManager::soundTriggerSupportsConcurrentCapture() {
-    if (!mHasComputedSoundTriggerSupportsConcurrentCapture) {
-        bool soundTriggerSupportsConcurrentCapture = false;
-        unsigned int numModules = 0;
-        struct sound_trigger_module_descriptor* nModules = NULL;
-
-        status_t status = SoundTrigger::listModules(nModules, &numModules);
-        if (status == NO_ERROR && numModules != 0) {
-            nModules = (struct sound_trigger_module_descriptor*) calloc(
-                    numModules, sizeof(struct sound_trigger_module_descriptor));
-            if (nModules == NULL) {
-              // We failed to malloc the buffer, so just say no for now, and hope that we have more
-              // ram the next time this function is called.
-              ALOGE("Failed to allocate buffer for module descriptors");
-              return false;
-            }
-
-            status = SoundTrigger::listModules(nModules, &numModules);
-            if (status == NO_ERROR) {
-                soundTriggerSupportsConcurrentCapture = true;
-                for (size_t i = 0; i < numModules; ++i) {
-                    soundTriggerSupportsConcurrentCapture &=
-                            nModules[i].properties.concurrent_capture;
-                }
-            }
-            free(nModules);
-        }
-        mSoundTriggerSupportsConcurrentCapture = soundTriggerSupportsConcurrentCapture;
-        mHasComputedSoundTriggerSupportsConcurrentCapture = true;
-    }
-    return mSoundTriggerSupportsConcurrentCapture;
-}
-
-
-status_t AudioPolicyManager::startInput(audio_port_handle_t portId,
-                                        bool silenced,
-                                        concurrency_type__mask_t *concurrency)
-{
-    *concurrency = API_INPUT_CONCURRENCY_NONE;
-
     ALOGV("%s portId %d", __FUNCTION__, portId);
 
     sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
@@ -1982,106 +1985,16 @@
 
     audio_session_t session = client->session();
 
-    ALOGV("%s input:%d, session:%d, silenced:%d, concurrency:%d)",
-        __FUNCTION__, input, session, silenced, *concurrency);
+    ALOGV("%s input:%d, session:%d)", __FUNCTION__, input, session);
 
-    if (!is_virtual_input_device(inputDesc->mDevice)) {
-        if (mCallTxPatch != 0 &&
-            inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
-            ALOGW("startInput(%d) failed: call in progress", input);
-            *concurrency |= API_INPUT_CONCURRENCY_CALL;
-            return INVALID_OPERATION;
-        }
+    Vector<sp<AudioInputDescriptor>> activeInputs = mInputs.getActiveInputs();
 
-        Vector<sp<AudioInputDescriptor>> activeInputs = mInputs.getActiveInputs();
-
-        // If a UID is idle and records silence and another not silenced recording starts
-        // from another UID (idle or active) we stop the current idle UID recording in
-        // favor of the new one - "There can be only one" TM
-        if (!silenced) {
-            for (const auto& activeDesc : activeInputs) {
-                if ((activeDesc->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
-                        activeDesc->getId() == inputDesc->getId()) {
-                     continue;
-                }
-
-                RecordClientVector activeClients = activeDesc->clientsList(true /*activeOnly*/);
-                for (const auto& activeClient : activeClients) {
-                    if (activeClient->isSilenced()) {
-                        closeClient(activeClient->portId());
-                        ALOGV("%s client %d stopping silenced client %d", __FUNCTION__,
-                              portId, activeClient->portId());
-                        activeInputs = mInputs.getActiveInputs();
-                    }
-                }
-            }
-        }
-
-        for (const auto& activeDesc : activeInputs) {
-            if ((client->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
-                    activeDesc->getId() == inputDesc->getId()) {
-                continue;
-            }
-
-            audio_source_t activeSource = activeDesc->inputSource(true);
-            if (client->source() == AUDIO_SOURCE_HOTWORD) {
-                if (activeSource == AUDIO_SOURCE_HOTWORD) {
-                    if (activeDesc->hasPreemptedSession(session)) {
-                        ALOGW("%s input %d failed for HOTWORD: "
-                                "other input %d already started for HOTWORD", __FUNCTION__,
-                              input, activeDesc->mIoHandle);
-                        *concurrency |= API_INPUT_CONCURRENCY_HOTWORD;
-                        return INVALID_OPERATION;
-                    }
-                } else {
-                    ALOGV("%s input %d failed for HOTWORD: other input %d already started",
-                        __FUNCTION__, input, activeDesc->mIoHandle);
-                    *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
-                    return INVALID_OPERATION;
-                }
-            } else {
-                if (activeSource != AUDIO_SOURCE_HOTWORD) {
-                    ALOGW("%s input %d failed: other input %d already started", __FUNCTION__,
-                          input, activeDesc->mIoHandle);
-                    *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
-                    return INVALID_OPERATION;
-                }
-            }
-        }
-
-        // We only need to check if the sound trigger session supports concurrent capture if the
-        // input is also a sound trigger input. Otherwise, we should preempt any hotword stream
-        // that's running.
-        const bool allowConcurrentWithSoundTrigger =
-            inputDesc->isSoundTrigger() ? soundTriggerSupportsConcurrentCapture() : false;
-
-        // if capture is allowed, preempt currently active HOTWORD captures
-        for (const auto& activeDesc : activeInputs) {
-            if (allowConcurrentWithSoundTrigger && activeDesc->isSoundTrigger()) {
-                continue;
-            }
-            RecordClientVector activeHotwordClients =
-                activeDesc->clientsList(true, AUDIO_SOURCE_HOTWORD);
-            if (activeHotwordClients.size() > 0) {
-                SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
-
-                for (const auto& activeClient : activeHotwordClients) {
-                    *concurrency |= API_INPUT_CONCURRENCY_PREEMPT;
-                    sessions.add(activeClient->session());
-                    closeClient(activeClient->portId());
-                    ALOGV("%s input %d for HOTWORD preempting HOTWORD input %d", __FUNCTION__,
-                          input, activeDesc->mIoHandle);
-                }
-
-                inputDesc->setPreemptedSessions(sessions);
-            }
-        }
+    status_t status = inputDesc->start();
+    if (status != NO_ERROR) {
+        return status;
     }
 
-    // Make sure we start with the correct silence state
-    client->setSilenced(silenced);
-
-    // increment activity count before calling getNewInputDevice() below as only active sessions
+  // increment activity count before calling getNewInputDevice() below as only active sessions
     // are considered for device selection
     inputDesc->setClientActive(client, true);
 
@@ -2090,12 +2003,6 @@
     audio_devices_t device = getNewInputDevice(inputDesc);
     setInputDevice(input, device, true /* force */);
 
-    status_t status = inputDesc->start();
-    if (status != NO_ERROR) {
-        inputDesc->setClientActive(client, false);
-        return status;
-    }
-
     if (inputDesc->activeCount()  == 1) {
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((inputDesc->mPolicyMix != NULL)
@@ -2314,7 +2221,7 @@
     status_t status = NO_ERROR;
     for (size_t i = 0; i < mOutputs.size(); i++) {
         sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
-        audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
+        audio_devices_t curDevice = desc->device();
         for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
             if (!(streamsMatchForvolume(stream, (audio_stream_type_t)curStream))) {
                 continue;
@@ -2332,7 +2239,7 @@
             bool applyVolume;
             if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
                 curStreamDevice |= device;
-                applyVolume = (curDevice & curStreamDevice) != 0;
+                applyVolume = (Volume::getDeviceForVolume(curDevice) & curStreamDevice) != 0;
             } else {
                 applyVolume = !mVolumeCurves->hasVolumeIndexForDevice(
                         stream, curStreamDevice);
@@ -2668,6 +2575,19 @@
     return res;
 }
 
+void AudioPolicyManager::dumpManualSurroundFormats(String8 *dst) const
+{
+    size_t i = 0;
+    constexpr size_t audioFormatPrefixLen = sizeof("AUDIO_FORMAT_");
+    for (const auto& fmt : mManualSurroundFormats) {
+        if (i++ != 0) dst->append(", ");
+        std::string sfmt;
+        FormatConverter::toString(fmt, sfmt);
+        dst->append(sfmt.size() >= audioFormatPrefixLen ?
+                sfmt.c_str() + audioFormatPrefixLen - 1 : sfmt.c_str());
+    }
+}
+
 void AudioPolicyManager::dump(String8 *dst) const
 {
     dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@@ -2681,8 +2601,15 @@
         "HDMI system audio", "encoded surround output", "vibrate ringing" };
     for (audio_policy_force_use_t i = AUDIO_POLICY_FORCE_FOR_COMMUNICATION;
          i < AUDIO_POLICY_FORCE_USE_CNT; i = (audio_policy_force_use_t)((int)i + 1)) {
-        dst->appendFormat(" Force use for %s: %d\n",
-                forceUses[i], mEngine->getForceUse(i));
+        audio_policy_forced_cfg_t forceUseValue = mEngine->getForceUse(i);
+        dst->appendFormat(" Force use for %s: %d", forceUses[i], forceUseValue);
+        if (i == AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND &&
+                forceUseValue == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
+            dst->append(" (MANUAL: ");
+            dumpManualSurroundFormats(dst);
+            dst->append(")");
+        }
+        dst->append("\n");
     }
     dst->appendFormat(" TTS output %savailable\n", mTtsOutputAvailable ? "" : "not ");
     dst->appendFormat(" Master mono: %s\n", mMasterMono ? "on" : "off");
@@ -2697,17 +2624,6 @@
     mAudioPatches.dump(dst);
     mPolicyMixes.dump(dst);
     mAudioSources.dump(dst);
-    if (!mSurroundFormats.empty()) {
-        dst->append("\nEnabled Surround Formats:\n");
-        size_t i = 0;
-        for (const auto& fmt : mSurroundFormats) {
-            dst->append(i++ == 0 ? "  " : ", ");
-            std::string sfmt;
-            FormatConverter::toString(fmt, sfmt);
-            dst->append(sfmt.c_str());
-        }
-        dst->append("\n");
-    }
 }
 
 status_t AudioPolicyManager::dump(int fd)
@@ -2781,15 +2697,34 @@
 
     // See if there is a profile to support this.
     // AUDIO_DEVICE_NONE
-    sp<IOProfile> profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */,
+    sp<IOProfile> profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */,
                                             offloadInfo.sample_rate,
                                             offloadInfo.format,
                                             offloadInfo.channel_mask,
-                                            AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
+                                            AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,
+                                            true /* directOnly */);
     ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT ");
     return (profile != 0);
 }
 
+bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& config,
+                                                 const audio_attributes_t& attributes) {
+    audio_output_flags_t output_flags = AUDIO_OUTPUT_FLAG_NONE;
+    audio_attributes_flags_to_audio_output_flags(attributes.flags, output_flags);
+    sp<IOProfile> profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */,
+                                            config.sample_rate,
+                                            config.format,
+                                            config.channel_mask,
+                                            output_flags,
+                                            true /* directOnly */);
+    ALOGV("%s() profile %sfound with name: %s, "
+        "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
+        __FUNCTION__, profile != 0 ? "" : "NOT ",
+        (profile != 0 ? profile->getTagName().string() : "null"),
+        config.sample_rate, config.format, config.channel_mask, output_flags);
+    return (profile != 0);
+}
+
 status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
                                             audio_port_type_t type,
                                             unsigned int *num_ports,
@@ -3344,7 +3279,7 @@
     SortedVector<audio_io_handle_t> inputsToClose;
     for (size_t i = 0; i < mInputs.size(); i++) {
         sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
-        if (affectedSources.indexOf(inputDesc->inputSource()) >= 0) {
+        if (affectedSources.indexOf(inputDesc->source()) >= 0) {
             inputsToClose.add(inputDesc->mIoHandle);
         }
     }
@@ -3567,63 +3502,56 @@
             (surroundFormats == NULL || surroundFormatsEnabled == NULL))) {
         return BAD_VALUE;
     }
-    ALOGV("getSurroundFormats() numSurroundFormats %d surroundFormats %p surroundFormatsEnabled %p"
-            " reported %d", *numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
-
-    // Only return value if there is HDMI output.
-    if ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_HDMI) == 0) {
-        return INVALID_OPERATION;
-    }
+    ALOGV("%s() numSurroundFormats %d surroundFormats %p surroundFormatsEnabled %p reported %d",
+            __func__, *numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
 
     size_t formatsWritten = 0;
     size_t formatsMax = *numSurroundFormats;
-    *numSurroundFormats = 0;
-    std::unordered_set<audio_format_t> formats;
+    std::unordered_set<audio_format_t> formats; // Uses primary surround formats only
     if (reported) {
-        // Return formats from HDMI profiles, that have already been resolved by
+        // Return formats from all device profiles that have already been resolved by
         // checkOutputsForDevice().
-        DeviceVector hdmiOutputDevs = mAvailableOutputDevices.getDevicesFromTypeMask(
-              AUDIO_DEVICE_OUT_HDMI);
-        for (size_t i = 0; i < hdmiOutputDevs.size(); i++) {
-             FormatVector supportedFormats =
-                 hdmiOutputDevs[i]->getAudioPort()->getAudioProfiles().getSupportedFormats();
-             for (size_t j = 0; j < supportedFormats.size(); j++) {
-                 if (mConfig.getSurroundFormats().count(supportedFormats[j]) != 0) {
-                     formats.insert(supportedFormats[j]);
-                 } else {
-                     for (const auto& pair : mConfig.getSurroundFormats()) {
-                         if (pair.second.count(supportedFormats[j]) != 0) {
-                             formats.insert(pair.first);
-                             break;
-                         }
-                     }
-                 }
-             }
+        for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
+            sp<DeviceDescriptor> device = mAvailableOutputDevices[i];
+            FormatVector supportedFormats =
+                    device->getAudioPort()->getAudioProfiles().getSupportedFormats();
+            for (size_t j = 0; j < supportedFormats.size(); j++) {
+                if (mConfig.getSurroundFormats().count(supportedFormats[j]) != 0) {
+                    formats.insert(supportedFormats[j]);
+                } else {
+                    for (const auto& pair : mConfig.getSurroundFormats()) {
+                        if (pair.second.count(supportedFormats[j]) != 0) {
+                            formats.insert(pair.first);
+                            break;
+                        }
+                    }
+                }
+            }
         }
     } else {
         for (const auto& pair : mConfig.getSurroundFormats()) {
             formats.insert(pair.first);
         }
     }
+    *numSurroundFormats = formats.size();
+    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
+            AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
     for (const auto& format: formats) {
         if (formatsWritten < formatsMax) {
             surroundFormats[formatsWritten] = format;
-            bool formatEnabled = false;
-            if (mConfig.getSurroundFormats().count(format) == 0) {
-                // Check sub-formats
-                for (const auto& pair : mConfig.getSurroundFormats()) {
-                    for (const auto& subformat : pair.second) {
-                        formatEnabled = mSurroundFormats.count(subformat) != 0;
-                        if (formatEnabled) break;
-                    }
-                    if (formatEnabled) break;
-                }
-            } else {
-                formatEnabled = mSurroundFormats.count(format) != 0;
+            bool formatEnabled = true;
+            switch (forceUse) {
+                case AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL:
+                    formatEnabled = mManualSurroundFormats.count(format) != 0;
+                    break;
+                case AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER:
+                    formatEnabled = false;
+                    break;
+                default: // AUTO or ALWAYS => true
+                    break;
             }
             surroundFormatsEnabled[formatsWritten++] = formatEnabled;
         }
-        (*numSurroundFormats)++;
     }
     return NO_ERROR;
 }
@@ -3631,41 +3559,32 @@
 status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat, bool enabled)
 {
     ALOGV("%s() format 0x%X enabled %d", __func__, audioFormat, enabled);
-    // Check if audio format is a surround formats.
     const auto& formatIter = mConfig.getSurroundFormats().find(audioFormat);
     if (formatIter == mConfig.getSurroundFormats().end()) {
         ALOGW("%s() format 0x%X is not a known surround format", __func__, audioFormat);
         return BAD_VALUE;
     }
 
-    // Should only be called when MANUAL.
-    audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
-                AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
-    if (forceUse != AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
+    if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND) !=
+            AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
         ALOGW("%s() not in manual mode for surround sound format selection", __func__);
         return INVALID_OPERATION;
     }
 
-    if ((mSurroundFormats.count(audioFormat) != 0) == enabled) {
+    if ((mManualSurroundFormats.count(audioFormat) != 0) == enabled) {
         return NO_ERROR;
     }
 
-    // The operation is valid only when there is HDMI output available.
-    if ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_HDMI) == 0) {
-        ALOGW("%s() no HDMI out devices found", __func__);
-        return INVALID_OPERATION;
-    }
-
-    std::unordered_set<audio_format_t> surroundFormatsBackup(mSurroundFormats);
+    std::unordered_set<audio_format_t> surroundFormatsBackup(mManualSurroundFormats);
     if (enabled) {
-        mSurroundFormats.insert(audioFormat);
+        mManualSurroundFormats.insert(audioFormat);
         for (const auto& subFormat : formatIter->second) {
-            mSurroundFormats.insert(subFormat);
+            mManualSurroundFormats.insert(subFormat);
         }
     } else {
-        mSurroundFormats.erase(audioFormat);
+        mManualSurroundFormats.erase(audioFormat);
         for (const auto& subFormat : formatIter->second) {
-            mSurroundFormats.erase(subFormat);
+            mManualSurroundFormats.erase(subFormat);
         }
     }
 
@@ -3690,6 +3609,7 @@
                                              name.c_str());
         profileUpdated |= (status == NO_ERROR);
     }
+    // FIXME: Why doing this for input HDMI devices if we don't augment their reported formats?
     DeviceVector hdmiInputDevices = mAvailableInputDevices.getDevicesFromTypeMask(
                 AUDIO_DEVICE_IN_HDMI);
     for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
@@ -3712,7 +3632,7 @@
 
     if (!profileUpdated) {
         ALOGW("%s() no audio profiles updated, undoing surround formats change", __func__);
-        mSurroundFormats = std::move(surroundFormatsBackup);
+        mManualSurroundFormats = std::move(surroundFormatsBackup);
     }
 
     return profileUpdated ? NO_ERROR : INVALID_OPERATION;
@@ -3721,16 +3641,15 @@
 void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
 {
     Vector<sp<AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
-    bool silenced = state == APP_STATE_IDLE;
 
-    ALOGV("AudioPolicyManager:setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);
+    ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
 
     for (size_t i = 0; i < activeInputs.size(); i++) {
         sp<AudioInputDescriptor> activeDesc = activeInputs[i];
         RecordClientVector clients = activeDesc->clientsList(true /*activeOnly*/);
         for (const auto& client : clients) {
             if (uid == client->uid()) {
-                client->setSilenced(silenced);
+                client->setAppState(state);
             }
         }
     }
@@ -3857,8 +3776,7 @@
     mBeaconMuted(false),
     mTtsOutputAvailable(false),
     mMasterMono(false),
-    mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
-    mHasComputedSoundTriggerSupportsConcurrentCapture(false)
+    mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
 {
 }
 
@@ -4107,7 +4025,7 @@
    mInputs.clear();
    mHwModules.clear();
    mHwModulesAll.clear();
-   mSurroundFormats.clear();
+   mManualSurroundFormats.clear();
 }
 
 status_t AudioPolicyManager::initCheck()
@@ -4245,7 +4163,7 @@
                     mpClientInterface->setParameters(output, String8(param));
                     free(param);
                 }
-                updateAudioProfiles(device, output, profile->getAudioProfiles());
+                updateAudioProfiles(devDesc, output, profile->getAudioProfiles());
                 if (!profile->hasValidAudioProfile()) {
                     ALOGW("checkOutputsForDevice() missing param");
                     desc->close();
@@ -4453,7 +4371,7 @@
                     mpClientInterface->setParameters(input, String8(param));
                     free(param);
                 }
-                updateAudioProfiles(device, input, profile->getAudioProfiles());
+                updateAudioProfiles(devDesc, input, profile->getAudioProfiles());
                 if (!profile->hasValidAudioProfile()) {
                     ALOGW("checkInputsForDevice() direct input missing param");
                     desc->close();
@@ -4573,7 +4491,7 @@
 
     // MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if
     // no direct outputs are open.
-    if (getMsdAudioOutDeviceTypes() != AUDIO_DEVICE_NONE) {
+    if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
         bool directOutputOpen = false;
         for (size_t i = 0; i < mOutputs.size(); i++) {
             if (mOutputs[i]->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
@@ -4911,7 +4829,7 @@
 
     // If we are not in call and no client is active on this input, this methods returns
     // AUDIO_DEVICE_NONE, causing the patch on the input stream to be released.
-    audio_source_t source = inputDesc->getHighestPrioritySource(true /*activeOnly*/);
+    audio_source_t source = inputDesc->source();
     if (source == AUDIO_SOURCE_DEFAULT && isInCall()) {
         source = AUDIO_SOURCE_VOICE_COMMUNICATION;
     }
@@ -5250,20 +5168,6 @@
             }
             installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
         }
-
-        // inform all input as well
-        for (size_t i = 0; i < mInputs.size(); i++) {
-            const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i);
-            if (!is_virtual_input_device(inputDescriptor->mDevice)) {
-                AudioParameter inputCmd = AudioParameter();
-                ALOGV("%s: inform input %d of device:%d", __func__,
-                      inputDescriptor->mIoHandle, device);
-                inputCmd.addInt(String8(AudioParameter::keyRouting),device);
-                mpClientInterface->setParameters(inputDescriptor->mIoHandle,
-                                                 inputCmd.toString(),
-                                                 delayMs);
-            }
-        }
     }
 
     // update stream volumes according to new device
@@ -5806,117 +5710,61 @@
     }
 }
 
-// Modify the list of surround sound formats supported.
-void AudioPolicyManager::filterSurroundFormats(FormatVector *formatsPtr) {
-    FormatVector &formats = *formatsPtr;
-    // TODO Set this based on Config properties.
-    const bool alwaysForceAC3 = true;
+void AudioPolicyManager::modifySurroundFormats(
+        const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr) {
+    std::unordered_set<audio_format_t> enforcedSurround(
+            devDesc->encodedFormats().begin(), devDesc->encodedFormats().end());
+    std::unordered_set<audio_format_t> allSurround;  // A flat set of all known surround formats
+    for (const auto& pair : mConfig.getSurroundFormats()) {
+        allSurround.insert(pair.first);
+        for (const auto& subformat : pair.second) allSurround.insert(subformat);
+    }
 
     audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
             AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
     ALOGD("%s: forced use = %d", __FUNCTION__, forceUse);
+    // This is the resulting set of formats depending on the surround mode:
+    //   'all surround' = allSurround
+    //   'enforced surround' = enforcedSurround [may include IEC69137 which isn't raw surround fmt]
+    //   'non-surround' = not in 'all surround' and not in 'enforced surround'
+    //   'manual surround' = mManualSurroundFormats
+    // AUTO:   formats v 'enforced surround'
+    // ALWAYS: formats v 'all surround' v 'enforced surround'
+    // NEVER:  formats ^ 'non-surround'
+    // MANUAL: formats ^ ('non-surround' v 'manual surround' v (IEC69137 ^ 'enforced surround'))
 
-    // If MANUAL, keep the supported surround sound formats as current enabled ones.
+    std::unordered_set<audio_format_t> formatSet;
+    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL
+            || forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
+        // formatSet is (formats ^ 'non-surround')
+        for (auto formatIter = formatsPtr->begin(); formatIter != formatsPtr->end(); ++formatIter) {
+            if (allSurround.count(*formatIter) == 0 && enforcedSurround.count(*formatIter) == 0) {
+                formatSet.insert(*formatIter);
+            }
+        }
+    } else {
+        formatSet.insert(formatsPtr->begin(), formatsPtr->end());
+    }
+    formatsPtr->clear();  // Re-filled from the formatSet at the end.
+
     if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
-        formats.clear();
-        for (auto it = mSurroundFormats.begin(); it != mSurroundFormats.end(); it++) {
-            formats.add(*it);
+        formatSet.insert(mManualSurroundFormats.begin(), mManualSurroundFormats.end());
+        // Enable IEC61937 when in MANUAL mode if it's enforced for this device.
+        if (enforcedSurround.count(AUDIO_FORMAT_IEC61937) != 0) {
+            formatSet.insert(AUDIO_FORMAT_IEC61937);
         }
-        // Always enable IEC61937 when in MANUAL mode.
-        formats.add(AUDIO_FORMAT_IEC61937);
-    } else { // NEVER, AUTO or ALWAYS
-        // Analyze original support for various formats.
-        bool supportsAC3 = false;
-        bool supportsOtherSurround = false;
-        bool supportsIEC61937 = false;
-        mSurroundFormats.clear();
-        for (ssize_t formatIndex = 0; formatIndex < (ssize_t)formats.size(); formatIndex++) {
-            audio_format_t format = formats[formatIndex];
-            switch (format) {
-                case AUDIO_FORMAT_AC3:
-                    supportsAC3 = true;
-                    break;
-                case AUDIO_FORMAT_E_AC3:
-                case AUDIO_FORMAT_DTS:
-                case AUDIO_FORMAT_DTS_HD:
-                    // If ALWAYS, remove all other surround formats here
-                    // since we will add them later.
-                    if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
-                        formats.removeAt(formatIndex);
-                        formatIndex--;
-                    }
-                    supportsOtherSurround = true;
-                    break;
-                case AUDIO_FORMAT_IEC61937:
-                    supportsIEC61937 = true;
-                    break;
-                default:
-                    break;
-            }
+    } else if (forceUse != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) { // AUTO or ALWAYS
+        if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
+            formatSet.insert(allSurround.begin(), allSurround.end());
         }
-
-        // Modify formats based on surround preferences.
-        // If NEVER, remove support for surround formats.
-        if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER) {
-            if (supportsAC3 || supportsOtherSurround || supportsIEC61937) {
-                // Remove surround sound related formats.
-                for (size_t formatIndex = 0; formatIndex < formats.size(); ) {
-                    audio_format_t format = formats[formatIndex];
-                    switch(format) {
-                        case AUDIO_FORMAT_AC3:
-                        case AUDIO_FORMAT_E_AC3:
-                        case AUDIO_FORMAT_DTS:
-                        case AUDIO_FORMAT_DTS_HD:
-                        case AUDIO_FORMAT_IEC61937:
-                            formats.removeAt(formatIndex);
-                            break;
-                        default:
-                            formatIndex++; // keep it
-                            break;
-                    }
-                }
-                supportsAC3 = false;
-                supportsOtherSurround = false;
-                supportsIEC61937 = false;
-            }
-        } else { // AUTO or ALWAYS
-            // Most TVs support AC3 even if they do not report it in the EDID.
-            if ((alwaysForceAC3 || (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS))
-                    && !supportsAC3) {
-                formats.add(AUDIO_FORMAT_AC3);
-                supportsAC3 = true;
-            }
-
-            // If ALWAYS, add support for raw surround formats if all are missing.
-            // This assumes that if any of these formats are reported by the HAL
-            // then the report is valid and should not be modified.
-            if (forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
-                formats.add(AUDIO_FORMAT_E_AC3);
-                formats.add(AUDIO_FORMAT_DTS);
-                formats.add(AUDIO_FORMAT_DTS_HD);
-                supportsOtherSurround = true;
-            }
-
-            // Add support for IEC61937 if any raw surround supported.
-            // The HAL could do this but add it here, just in case.
-            if ((supportsAC3 || supportsOtherSurround) && !supportsIEC61937) {
-                formats.add(AUDIO_FORMAT_IEC61937);
-                supportsIEC61937 = true;
-            }
-
-            // Add reported surround sound formats to enabled surround formats.
-            for (size_t formatIndex = 0; formatIndex < formats.size(); formatIndex++) {
-                audio_format_t format = formats[formatIndex];
-                if (mConfig.getSurroundFormats().count(format) != 0) {
-                    mSurroundFormats.insert(format);
-                }
-            }
-        }
+        formatSet.insert(enforcedSurround.begin(), enforcedSurround.end());
+    }
+    for (const auto& format : formatSet) {
+        formatsPtr->push(format);
     }
 }
 
-// Modify the list of channel masks supported.
-void AudioPolicyManager::filterSurroundChannelMasks(ChannelsVector *channelMasksPtr) {
+void AudioPolicyManager::modifySurroundChannelMasks(ChannelsVector *channelMasksPtr) {
     ChannelsVector &channelMasks = *channelMasksPtr;
     audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
             AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
@@ -5946,16 +5794,17 @@
         // If not then add 5.1 support.
         if (!supports5dot1) {
             channelMasks.add(AUDIO_CHANNEL_OUT_5POINT1);
-            ALOGI("%s: force ALWAYS, so adding channelMask for 5.1 surround", __FUNCTION__);
+            ALOGI("%s: force MANUAL or ALWAYS, so adding channelMask for 5.1 surround", __func__);
         }
     }
 }
 
-void AudioPolicyManager::updateAudioProfiles(audio_devices_t device,
+void AudioPolicyManager::updateAudioProfiles(const sp<DeviceDescriptor>& devDesc,
                                              audio_io_handle_t ioHandle,
                                              AudioProfileVector &profiles)
 {
     String8 reply;
+    audio_devices_t device = devDesc->type();
 
     // Format MUST be checked first to update the list of AudioProfile
     if (profiles.hasDynamicFormat()) {
@@ -5969,8 +5818,9 @@
             return;
         }
         FormatVector formats = formatsFromString(reply.string());
-        if (device == AUDIO_DEVICE_OUT_HDMI) {
-            filterSurroundFormats(&formats);
+        if (device == AUDIO_DEVICE_OUT_HDMI
+                || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
+            modifySurroundFormats(devDesc, &formats);
         }
         profiles.setFormats(formats);
     }
@@ -6002,8 +5852,9 @@
             if (repliedParameters.get(
                     String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
                 channelMasks = channelMasksFromString(reply.string());
-                if (device == AUDIO_DEVICE_OUT_HDMI) {
-                    filterSurroundChannelMasks(&channelMasks);
+                if (device == AUDIO_DEVICE_OUT_HDMI
+                        || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
+                    modifySurroundChannelMasks(&channelMasks);
                 }
             }
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index c85ecf6..7f2412e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -134,9 +134,7 @@
                                          audio_port_handle_t *portId);
 
         // indicates to the audio policy manager that the input starts being used.
-        virtual status_t startInput(audio_port_handle_t portId,
-                                    bool silenced,
-                                    concurrency_type__mask_t *concurrency);
+        virtual status_t startInput(audio_port_handle_t portId);
 
         // indicates to the audio policy manager that the input stops being used.
         virtual status_t stopInput(audio_port_handle_t portId);
@@ -186,12 +184,17 @@
 
         virtual bool isSourceActive(audio_source_t source) const;
 
-        void dump(String8 *dst) const; // helper for dump(int fd)
+        // helpers for dump(int fd)
+        void dumpManualSurroundFormats(String8 *dst) const;
+        void dump(String8 *dst) const;
 
         status_t dump(int fd) override;
 
         virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
 
+        virtual bool isDirectOutputSupported(const audio_config_base_t& config,
+                                             const audio_attributes_t& attributes);
+
         virtual status_t listAudioPorts(audio_port_role_t role,
                                         audio_port_type_t type,
                                         unsigned int *num_ports,
@@ -481,11 +484,12 @@
                                       audio_format_t& format,
                                       audio_channel_mask_t& channelMask,
                                       audio_input_flags_t flags);
-        sp<IOProfile> getProfileForDirectOutput(audio_devices_t device,
-                                                       uint32_t samplingRate,
-                                                       audio_format_t format,
-                                                       audio_channel_mask_t channelMask,
-                                                       audio_output_flags_t flags);
+        sp<IOProfile> getProfileForOutput(audio_devices_t device,
+                                          uint32_t samplingRate,
+                                          audio_format_t format,
+                                          audio_channel_mask_t channelMask,
+                                          audio_output_flags_t flags,
+                                          bool directOnly);
 
         audio_io_handle_t selectOutputForMusicEffects();
 
@@ -518,6 +522,9 @@
         sp<AudioPatch> createTelephonyPatch(bool isRx, audio_devices_t device, uint32_t delayMs);
         sp<DeviceDescriptor> findDevice(
                 const DeviceVector& devices, audio_devices_t device) const;
+        audio_devices_t getModuleDeviceTypes(
+                const DeviceVector& devices, const char *moduleId) const;
+        bool isDeviceOfModule(const sp<DeviceDescriptor>& devDesc, const char *moduleId) const;
 
         status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
                              const sp<TrackClientDescriptor>& client,
@@ -541,8 +548,6 @@
 
         void clearAudioSources(uid_t uid);
 
-        static bool isConcurrentSource(audio_source_t source);
-
         static bool streamsMatchForvolume(audio_stream_type_t stream1,
                                           audio_stream_type_t stream2);
 
@@ -610,16 +615,16 @@
         // Audio Policy Engine Interface.
         AudioPolicyManagerInterface *mEngine;
 
-        // Surround formats that are enabled.
-        std::unordered_set<audio_format_t> mSurroundFormats;
+        // Surround formats that are enabled manually. Taken into account when
+        // "encoded surround" is forced into "manual" mode.
+        std::unordered_set<audio_format_t> mManualSurroundFormats;
 private:
         // Add or remove AC3 DTS encodings based on user preferences.
-        void filterSurroundFormats(FormatVector *formatsPtr);
-        void filterSurroundChannelMasks(ChannelsVector *channelMasksPtr);
+        void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
+        void modifySurroundChannelMasks(ChannelsVector *channelMasksPtr);
 
         // Support for Multi-Stream Decoder (MSD) module
         sp<DeviceDescriptor> getMsdAudioInDevice() const;
-        audio_devices_t getMsdAudioOutDeviceTypes() const;
         const AudioPatchCollection getMsdPatches() const;
         status_t getBestMsdAudioProfileFor(audio_devices_t outputDevice,
                                            bool hwAvSync,
@@ -629,7 +634,7 @@
         status_t setMsdPatch(audio_devices_t outputDevice = AUDIO_DEVICE_NONE);
 
         // If any, resolve any "dynamic" fields of an Audio Profiles collection
-        void updateAudioProfiles(audio_devices_t device, audio_io_handle_t ioHandle,
+        void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
                 AudioProfileVector &profiles);
 
         // Notify the policy client of any change of device state with AUDIO_IO_HANDLE_NONE,
@@ -706,10 +711,6 @@
                 int delayMs,
                 uid_t uid,
                 sp<AudioPatch> *patchDescPtr);
-
-        bool soundTriggerSupportsConcurrentCapture();
-        bool mSoundTriggerSupportsConcurrentCapture;
-        bool mHasComputedSoundTriggerSupportsConcurrentCapture;
 };
 
 };
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index cf72431..439764b 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -454,23 +454,6 @@
     return rawbuffer;
 }
 
-static std::string audioConcurrencyString(
-        AudioPolicyInterface::concurrency_type__mask_t concurrency)
-{
-    char buffer[64]; // oversized
-    if (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL) {
-        snprintf(buffer, sizeof(buffer), "%s%s%s%s",
-            (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CALL)? ",call":"",
-            (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CAPTURE)? ",capture":"",
-            (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_HOTWORD)? ",hotword":"",
-            (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_PREEMPT)? ",preempt":"");
-    } else {
-        snprintf(buffer, sizeof(buffer), ",none");
-    }
-
-    return &buffer[1];
-}
-
 std::string AudioPolicyService::getDeviceTypeStrForPortId(audio_port_handle_t portId) {
     std::string typeStr;
     struct audio_port port = {};
@@ -482,7 +465,7 @@
     return typeStr;
 }
 
-status_t AudioPolicyService::startInput(audio_port_handle_t portId, bool *silenced)
+status_t AudioPolicyService::startInput(audio_port_handle_t portId)
 {
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
@@ -505,17 +488,16 @@
         return PERMISSION_DENIED;
     }
 
-    // If UID inactive it records silence until becoming active
-    *silenced = !mUidPolicy->isUidActive(client->uid) && !client->isVirtualDevice;
-
     Mutex::Autolock _l(mLock);
-    AudioPolicyInterface::concurrency_type__mask_t concurrency =
-            AudioPolicyInterface::API_INPUT_CONCURRENCY_NONE;
+
+    client->active = true;
+    client->startTimeNs = systemTime();
+    updateUidStates_l();
 
     status_t status;
     {
         AutoCallerClear acc;
-        status = mAudioPolicyManager->startInput(portId, *silenced, &concurrency);
+        status = mAudioPolicyManager->startInput(portId);
 
     }
 
@@ -524,7 +506,6 @@
 
         static constexpr char kAudioPolicy[] = "audiopolicy";
 
-        static constexpr char kAudioPolicyReason[] = "android.media.audiopolicy.reason";
         static constexpr char kAudioPolicyStatus[] = "android.media.audiopolicy.status";
         static constexpr char kAudioPolicyRqstSrc[] = "android.media.audiopolicy.rqst.src";
         static constexpr char kAudioPolicyRqstPkg[] = "android.media.audiopolicy.rqst.pkg";
@@ -541,7 +522,6 @@
         MediaAnalyticsItem *item = new MediaAnalyticsItem(kAudioPolicy);
         if (item != NULL) {
 
-            item->setCString(kAudioPolicyReason, audioConcurrencyString(concurrency).c_str());
             item->setInt32(kAudioPolicyStatus, status);
 
             item->setCString(kAudioPolicyRqstSrc,
@@ -556,54 +536,35 @@
             item->setCString(
                     kAudioPolicyRqstDevice, getDeviceTypeStrForPortId(client->deviceId).c_str());
 
-            // figure out who is active
-            // NB: might the other party have given up the microphone since then? how sure.
-            // perhaps could have given up on it.
-            // we hold mLock, so perhaps we're safe for this looping
-            if (concurrency != AudioPolicyInterface::API_INPUT_CONCURRENCY_NONE) {
-                int count = mAudioRecordClients.size();
-                for (int i = 0; i<count ; i++) {
-                    if (portId == mAudioRecordClients.keyAt(i)) {
-                        continue;
+            int count = mAudioRecordClients.size();
+            for (int i = 0; i < count ; i++) {
+                if (portId == mAudioRecordClients.keyAt(i)) {
+                    continue;
+                }
+                sp<AudioRecordClient> other = mAudioRecordClients.valueAt(i);
+                if (other->active) {
+                    // keeps the last of the clients marked active
+                    item->setCString(kAudioPolicyActiveSrc,
+                                     audioSourceString(other->attributes.source).c_str());
+                    item->setInt32(kAudioPolicyActiveSession, other->session);
+                    if (other->opPackageName.size() != 0) {
+                        item->setCString(kAudioPolicyActivePkg,
+                             std::string(String8(other->opPackageName).string()).c_str());
+                    } else {
+                        item->setCString(kAudioPolicyRqstPkg,
+                                         std::to_string(other->uid).c_str());
                     }
-                    sp<AudioRecordClient> other = mAudioRecordClients.valueAt(i);
-                    if (other->active) {
-                        // keeps the last of the clients marked active
-                        item->setCString(kAudioPolicyActiveSrc,
-                                         audioSourceString(other->attributes.source).c_str());
-                        item->setInt32(kAudioPolicyActiveSession, other->session);
-                        if (other->opPackageName.size() != 0) {
-                            item->setCString(kAudioPolicyActivePkg,
-                                 std::string(String8(other->opPackageName).string()).c_str());
-                        } else {
-                            item->setCString(kAudioPolicyRqstPkg,
-                                             std::to_string(other->uid).c_str());
-                        }
-                        item->setCString(kAudioPolicyActiveDevice,
-                                         getDeviceTypeStrForPortId(other->deviceId).c_str());
-                    }
+                    item->setCString(kAudioPolicyActiveDevice,
+                                     getDeviceTypeStrForPortId(other->deviceId).c_str());
                 }
             }
             item->selfrecord();
             delete item;
             item = NULL;
         }
-    }
-
-    if (status == NO_ERROR) {
-        LOG_ALWAYS_FATAL_IF(concurrency & ~AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL,
-                            "startInput(): invalid concurrency type %d", (int)concurrency);
-
-        // enforce permission (if any) required for each type of concurrency
-        if (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CALL) {
-            //TODO: check incall capture permission
-        }
-        if (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CAPTURE) {
-            //TODO: check concurrent capture permission
-        }
-
-        client->active = true;
-    } else {
+        client->active = false;
+        client->startTimeNs = 0;
+        updateUidStates_l();
         finishRecording(client->opPackageName, client->uid);
     }
 
@@ -615,6 +576,7 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
+
     Mutex::Autolock _l(mLock);
 
     ssize_t index = mAudioRecordClients.indexOfKey(portId);
@@ -624,6 +586,9 @@
     sp<AudioRecordClient> client = mAudioRecordClients.valueAt(index);
 
     client->active = false;
+    client->startTimeNs = 0;
+
+    updateUidStates_l();
 
     // finish the recording app op
     finishRecording(client->opPackageName, client->uid);
@@ -646,6 +611,14 @@
             return;
         }
         client = mAudioRecordClients.valueAt(index);
+
+        if (client->active) {
+            ALOGW("%s releasing active client portId %d", __FUNCTION__, portId);
+            client->active = false;
+            client->startTimeNs = 0;
+            updateUidStates_l();
+        }
+
         mAudioRecordClients.removeItem(portId);
     }
     if (client == 0) {
@@ -936,6 +909,17 @@
     return mAudioPolicyManager->isOffloadSupported(info);
 }
 
+bool AudioPolicyService::isDirectOutputSupported(const audio_config_base_t& config,
+                                                 const audio_attributes_t& attributes) {
+    if (mAudioPolicyManager == NULL) {
+        ALOGV("mAudioPolicyManager == NULL");
+        return false;
+    }
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->isDirectOutputSupported(config, attributes);
+}
+
+
 status_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
                                             audio_port_type_t type,
                                             unsigned int *num_ports,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 018d9e3..ee5d6ff 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -340,14 +340,146 @@
     return NO_ERROR;
 }
 
-void AudioPolicyService::setAppState(uid_t uid, app_state_t state)
+void AudioPolicyService::updateUidStates()
 {
-    {
-        Mutex::Autolock _l(mLock);
-        if (mAudioPolicyManager) {
-            AutoCallerClear acc;
-            mAudioPolicyManager->setAppState(uid, state);
+    Mutex::Autolock _l(mLock);
+    updateUidStates_l();
+}
+
+void AudioPolicyService::updateUidStates_l()
+{
+//    Go over all active clients and allow capture (does not force silence) in the
+//    following cases:
+//    The client is the assistant
+//        AND an accessibility service is on TOP
+//               AND the source is VOICE_RECOGNITION or HOTWORD
+//        OR uses VOICE_RECOGNITION AND is on TOP OR latest started
+//               OR uses HOTWORD
+//            AND there is no privacy sensitive active capture
+//    OR The client is an accessibility service
+//        AND is on TOP OR latest started
+//        AND the source is VOICE_RECOGNITION or HOTWORD
+//    OR Any other client
+//        AND The assistant is not on TOP
+//        AND is on TOP OR latest started
+//        AND there is no privacy sensitive active capture
+//TODO: mamanage pre processing effects according to use case priority
+
+    sp<AudioRecordClient> topActive;
+    sp<AudioRecordClient> latestActive;
+    sp<AudioRecordClient> latestSensitiveActive;
+    nsecs_t topStartNs = 0;
+    nsecs_t latestStartNs = 0;
+    nsecs_t latestSensitiveStartNs = 0;
+    bool isA11yOnTop = mUidPolicy->isA11yOnTop();
+    bool isAssistantOnTop = false;
+    bool isSensitiveActive = false;
+
+    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
+        sp<AudioRecordClient> current = mAudioRecordClients[i];
+        if (!current->active) continue;
+        if (isPrivacySensitive(current->attributes.source)) {
+            if (current->startTimeNs > latestSensitiveStartNs) {
+                latestSensitiveActive = current;
+                latestSensitiveStartNs = current->startTimeNs;
+            }
+            isSensitiveActive = true;
         }
+        if (mUidPolicy->getUidState(current->uid) == ActivityManager::PROCESS_STATE_TOP) {
+            if (current->startTimeNs > topStartNs) {
+                topActive = current;
+                topStartNs = current->startTimeNs;
+            }
+            if (mUidPolicy->isAssistantUid(current->uid)) {
+                isAssistantOnTop = true;
+            }
+        }
+        if (current->startTimeNs > latestStartNs) {
+            latestActive = current;
+            latestStartNs = current->startTimeNs;
+        }
+    }
+
+    if (topActive == nullptr && latestActive == nullptr) {
+        return;
+    }
+
+    if (topActive != nullptr) {
+        latestActive = nullptr;
+    }
+
+    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
+        sp<AudioRecordClient> current = mAudioRecordClients[i];
+        if (!current->active) continue;
+
+        audio_source_t source = current->attributes.source;
+        bool isOnTop = current == topActive;
+        bool isLatest = current == latestActive;
+        bool isLatestSensitive = current == latestSensitiveActive;
+        bool forceIdle = true;
+        if (mUidPolicy->isAssistantUid(current->uid)) {
+            if (isA11yOnTop) {
+                if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+                    forceIdle = false;
+                }
+            } else {
+                if ((((isOnTop || isLatest) && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
+                     source == AUDIO_SOURCE_HOTWORD) && !isSensitiveActive) {
+                    forceIdle = false;
+                }
+            }
+        } else if (mUidPolicy->isA11yUid(current->uid)) {
+            if ((isOnTop || isLatest) &&
+                (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
+                forceIdle = false;
+            }
+        } else {
+            if (!isAssistantOnTop && (isOnTop || isLatest) &&
+                (!isSensitiveActive || isLatestSensitive)) {
+                forceIdle = false;
+            }
+        }
+        setAppState_l(current->uid,
+                      forceIdle ? APP_STATE_IDLE :
+                                  apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
+    }
+}
+
+/* static */
+app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
+    switch (amState) {
+    case ActivityManager::PROCESS_STATE_UNKNOWN:
+        return APP_STATE_IDLE;
+    case ActivityManager::PROCESS_STATE_TOP:
+        return APP_STATE_TOP;
+    default:
+        break;
+    }
+    return APP_STATE_FOREGROUND;
+}
+
+/* static */
+bool AudioPolicyService::isPrivacySensitive(audio_source_t source)
+{
+    switch (source) {
+        case AUDIO_SOURCE_VOICE_UPLINK:
+        case AUDIO_SOURCE_VOICE_DOWNLINK:
+        case AUDIO_SOURCE_VOICE_CALL:
+        case AUDIO_SOURCE_CAMCORDER:
+        case AUDIO_SOURCE_VOICE_COMMUNICATION:
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
+{
+    AutoCallerClear acc;
+
+    if (mAudioPolicyManager) {
+        mAudioPolicyManager->setAppState(uid, state);
     }
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
     if (af) {
@@ -511,7 +643,8 @@
     ActivityManager am;
     am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
             | ActivityManager::UID_OBSERVER_IDLE
-            | ActivityManager::UID_OBSERVER_ACTIVE,
+            | ActivityManager::UID_OBSERVER_ACTIVE
+            | ActivityManager::UID_OBSERVER_PROCSTATE,
             ActivityManager::PROCESS_STATE_UNKNOWN,
             String16("audioserver"));
     status_t res = am.linkToDeath(this);
@@ -520,6 +653,7 @@
         mObserverRegistered = true;
     } else {
         ALOGE("UidPolicy::registerSelf linkToDeath failed: %d", res);
+
         am.unregisterUidObserver(this);
     }
 }
@@ -538,8 +672,7 @@
     mObserverRegistered = false;
 }
 
-bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
-    if (isServiceUid(uid)) return true;
+void AudioPolicyService::UidPolicy::checkRegistered() {
     bool needToReregister = false;
     {
         Mutex::Autolock _l(mLock);
@@ -549,94 +682,176 @@
         // Looks like ActivityManager has died previously, attempt to re-register.
         registerSelf();
     }
+}
+
+bool AudioPolicyService::UidPolicy::isUidActive(uid_t uid) {
+    if (isServiceUid(uid)) return true;
+    checkRegistered();
     {
         Mutex::Autolock _l(mLock);
         auto overrideIter = mOverrideUids.find(uid);
         if (overrideIter != mOverrideUids.end()) {
-            return overrideIter->second;
+            return overrideIter->second.first;
         }
         // In an absense of the ActivityManager, assume everything to be active.
         if (!mObserverRegistered) return true;
         auto cacheIter = mCachedUids.find(uid);
         if (cacheIter != mCachedUids.end()) {
-            return cacheIter->second;
+            return cacheIter->second.first;
         }
     }
     ActivityManager am;
     bool active = am.isUidActive(uid, String16("audioserver"));
     {
         Mutex::Autolock _l(mLock);
-        mCachedUids.insert(std::pair<uid_t, bool>(uid, active));
+        mCachedUids.insert(std::pair<uid_t,
+                           std::pair<bool, int>>(uid, std::pair<bool, int>(active,
+                                                      ActivityManager::PROCESS_STATE_UNKNOWN)));
     }
     return active;
 }
 
+int AudioPolicyService::UidPolicy::getUidState(uid_t uid) {
+    if (isServiceUid(uid)) {
+        return ActivityManager::PROCESS_STATE_TOP;
+    }
+    checkRegistered();
+    {
+        Mutex::Autolock _l(mLock);
+        auto overrideIter = mOverrideUids.find(uid);
+        if (overrideIter != mOverrideUids.end()) {
+            if (overrideIter->second.first) {
+                if (overrideIter->second.second != ActivityManager::PROCESS_STATE_UNKNOWN) {
+                    return overrideIter->second.second;
+                } else {
+                    auto cacheIter = mCachedUids.find(uid);
+                    if (cacheIter != mCachedUids.end()) {
+                        return cacheIter->second.second;
+                    }
+                }
+            }
+            return ActivityManager::PROCESS_STATE_UNKNOWN;
+        }
+        // In an absense of the ActivityManager, assume everything to be active.
+        if (!mObserverRegistered) {
+            return ActivityManager::PROCESS_STATE_TOP;
+        }
+        auto cacheIter = mCachedUids.find(uid);
+        if (cacheIter != mCachedUids.end()) {
+            if (cacheIter->second.first) {
+                return cacheIter->second.second;
+            } else {
+                return ActivityManager::PROCESS_STATE_UNKNOWN;
+            }
+        }
+    }
+    ActivityManager am;
+    bool active = am.isUidActive(uid, String16("audioserver"));
+    int state = ActivityManager::PROCESS_STATE_UNKNOWN;
+    if (active) {
+        state = am.getUidProcessState(uid, String16("audioserver"));
+    }
+    {
+        Mutex::Autolock _l(mLock);
+        mCachedUids.insert(std::pair<uid_t,
+                           std::pair<bool, int>>(uid, std::pair<bool, int>(active, state)));
+    }
+
+    return state;
+}
+
 void AudioPolicyService::UidPolicy::onUidActive(uid_t uid) {
-    updateUidCache(uid, true, true);
+    updateUid(&mCachedUids, uid, true, ActivityManager::PROCESS_STATE_UNKNOWN, true);
 }
 
 void AudioPolicyService::UidPolicy::onUidGone(uid_t uid, __unused bool disabled) {
-    updateUidCache(uid, false, false);
+    updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, false);
 }
 
 void AudioPolicyService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) {
-    updateUidCache(uid, false, true);
+    updateUid(&mCachedUids, uid, false, ActivityManager::PROCESS_STATE_UNKNOWN, true);
 }
 
-void AudioPolicyService::UidPolicy::notifyService(uid_t uid, bool active) {
-    sp<AudioPolicyService> service = mService.promote();
-    if (service != nullptr) {
-        service->setAppState(uid, active ?
-                              APP_STATE_FOREGROUND :
-                              APP_STATE_IDLE);
+void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
+                                                      int32_t procState,
+                                                      int64_t procStateSeq __unused) {
+    if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) {
+        updateUid(&mCachedUids, uid, true, procState, true);
     }
 }
 
 void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
-    if (isServiceUid(uid)) return;
-    bool wasOverridden = false, wasActive = false;
-    {
-        Mutex::Autolock _l(mLock);
-        updateUidLocked(&mOverrideUids, uid, active, insert, &wasOverridden, &wasActive);
-    }
-    if (!wasOverridden && insert) {
-        notifyService(uid, active);  // Started to override.
-    } else if (wasOverridden && !insert) {
-        notifyService(uid, isUidActive(uid));  // Override ceased, notify with ground truth.
-    } else if (wasActive != active) {
-        notifyService(uid, active);  // Override updated.
+    updateUid(&mOverrideUids, uid, active, ActivityManager::PROCESS_STATE_UNKNOWN, insert);
+}
+
+void AudioPolicyService::UidPolicy::notifyService() {
+    sp<AudioPolicyService> service = mService.promote();
+    if (service != nullptr) {
+        service->updateUidStates();
     }
 }
 
-void AudioPolicyService::UidPolicy::updateUidCache(uid_t uid, bool active, bool insert) {
-    if (isServiceUid(uid)) return;
-    bool wasActive = false;
+void AudioPolicyService::UidPolicy::updateUid(std::unordered_map<uid_t,
+                                              std::pair<bool, int>> *uids,
+                                              uid_t uid,
+                                              bool active,
+                                              int state,
+                                              bool insert) {
+    if (isServiceUid(uid)) {
+        return;
+    }
+    bool wasActive = isUidActive(uid);
+    int previousState = getUidState(uid);
     {
         Mutex::Autolock _l(mLock);
-        updateUidLocked(&mCachedUids, uid, active, insert, nullptr, &wasActive);
-        // Do not notify service if currently overridden.
-        if (mOverrideUids.find(uid) != mOverrideUids.end()) return;
+        updateUidLocked(uids, uid, active, state, insert);
     }
-    bool nowActive = active && insert;
-    if (wasActive != nowActive) notifyService(uid, nowActive);
+    if (wasActive != isUidActive(uid) || state != previousState) {
+        notifyService();
+    }
 }
 
-void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t, bool> *uids,
-        uid_t uid, bool active, bool insert, bool *wasThere, bool *wasActive) {
+void AudioPolicyService::UidPolicy::updateUidLocked(std::unordered_map<uid_t,
+                                                    std::pair<bool, int>> *uids,
+                                                    uid_t uid,
+                                                    bool active,
+                                                    int state,
+                                                    bool insert) {
     auto it = uids->find(uid);
     if (it != uids->end()) {
-        if (wasThere != nullptr) *wasThere = true;
-        if (wasActive != nullptr) *wasActive = it->second;
         if (insert) {
-            it->second = active;
+            if (state == ActivityManager::PROCESS_STATE_UNKNOWN) {
+                it->second.first = active;
+            }
+            if (it->second.first) {
+                it->second.second = state;
+            } else {
+                it->second.second = ActivityManager::PROCESS_STATE_UNKNOWN;
+            }
         } else {
             uids->erase(it);
         }
-    } else if (insert) {
-        uids->insert(std::pair<uid_t, bool>(uid, active));
+    } else if (insert && (state == ActivityManager::PROCESS_STATE_UNKNOWN)) {
+        uids->insert(std::pair<uid_t, std::pair<bool, int>>(uid,
+                                      std::pair<bool, int>(active, state)));
     }
 }
 
+bool AudioPolicyService::UidPolicy::isA11yOnTop() {
+    for (const auto &uid : mCachedUids) {
+        std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid.first);
+        if (it == mA11yUids.end()) {
+            continue;
+        }
+        if (uid.second.second == ActivityManager::PROCESS_STATE_TOP ||
+            uid.second.second == ActivityManager::PROCESS_STATE_FOREGROUND_SERVICE ||
+            uid.second.second == ActivityManager::PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool AudioPolicyService::UidPolicy::isA11yUid(uid_t uid)
 {
     std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 7638c0c..23c3daa 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -94,8 +94,7 @@
                                      audio_input_flags_t flags,
                                      audio_port_handle_t *selectedDeviceId = NULL,
                                      audio_port_handle_t *portId = NULL);
-    virtual status_t startInput(audio_port_handle_t portId,
-                                bool *silenced);
+    virtual status_t startInput(audio_port_handle_t portId);
     virtual status_t stopInput(audio_port_handle_t portId);
     virtual void releaseInput(audio_port_handle_t portId);
     virtual status_t initStreamVolume(audio_stream_type_t stream,
@@ -168,6 +167,8 @@
                                      int delayMs = 0);
     virtual status_t setVoiceVolume(float volume, int delayMs = 0);
     virtual bool isOffloadSupported(const audio_offload_info_t &config);
+    virtual bool isDirectOutputSupported(const audio_config_base_t& config,
+                                         const audio_attributes_t& attributes);
 
     virtual status_t listAudioPorts(audio_port_role_t role,
                                     audio_port_type_t type,
@@ -255,7 +256,7 @@
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
     // Sets whether the given UID records only silence
-    virtual void setAppState(uid_t uid, app_state_t state);
+    virtual void setAppState_l(uid_t uid, app_state_t state);
 
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(Vector<String16>& args, int err);
@@ -273,6 +274,13 @@
 
     status_t getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects);
 
+    app_state_t apmStatFromAmState(int amState);
+
+    void updateUidStates();
+    void updateUidStates_l();
+
+    static bool isPrivacySensitive(audio_source_t source);
+
     // If recording we need to make sure the UID is allowed to do that. If the UID is idle
     // then it cannot record and gets buffers with zeros - silence. As soon as the UID
     // transitions to an active state we will start reporting buffers with data. This approach
@@ -291,31 +299,37 @@
         void binderDied(const wp<IBinder> &who) override;
 
         bool isUidActive(uid_t uid);
+        int getUidState(uid_t uid);
         void setAssistantUid(uid_t uid) { mAssistantUid = uid; }
         bool isAssistantUid(uid_t uid) { return uid == mAssistantUid; }
         void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
         bool isA11yUid(uid_t uid);
+        bool isA11yOnTop();
 
         // BnUidObserver implementation
         void onUidActive(uid_t uid) override;
         void onUidGone(uid_t uid, bool disabled) override;
         void onUidIdle(uid_t uid, bool disabled) override;
+        void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq);
 
         void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
         void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
 
-    private:
-        void notifyService(uid_t uid, bool active);
+        void updateUid(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
+                       uid_t uid, bool active, int state, bool insert);
+
+     private:
+        void notifyService();
         void updateOverrideUid(uid_t uid, bool active, bool insert);
-        void updateUidCache(uid_t uid, bool active, bool insert);
-        void updateUidLocked(std::unordered_map<uid_t, bool> *uids,
-                uid_t uid, bool active, bool insert, bool *wasThere, bool *wasActive);
+        void updateUidLocked(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
+                             uid_t uid, bool active, int state, bool insert);
+        void checkRegistered();
 
         wp<AudioPolicyService> mService;
         Mutex mLock;
         bool mObserverRegistered;
-        std::unordered_map<uid_t, bool> mOverrideUids;
-        std::unordered_map<uid_t, bool> mCachedUids;
+        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
+        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
         uid_t mAssistantUid;
         std::vector<uid_t> mA11yUids;
     };
@@ -642,12 +656,11 @@
                           const audio_session_t session, const audio_port_handle_t deviceId,
                           const String16& opPackageName) :
                     AudioClient(attributes, io, uid, pid, session, deviceId),
-                    opPackageName(opPackageName), isConcurrent(false), isVirtualDevice(false) {}
+                    opPackageName(opPackageName), startTimeNs(0) {}
                 ~AudioRecordClient() override = default;
 
         const String16 opPackageName;        // client package name
-        bool isConcurrent;             // is allowed to concurrent capture
-        bool isVirtualDevice;          // uses virtual device: updated by APM::getInputForAttr()
+        nsecs_t startTimeNs;
     };
 
     // --- AudioPlaybackClient ---
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
index 513312e..2ccb542 100644
--- a/services/audiopolicy/tests/Android.mk
+++ b/services/audiopolicy/tests/Android.mk
@@ -41,6 +41,9 @@
   libmedia_helper \
   libutils
 
+LOCAL_HEADER_LIBRARIES := \
+  libmedia_headers
+
 LOCAL_SRC_FILES := \
   systemaudio_tests.cpp \
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 32b07fa..6003607 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2215,6 +2215,8 @@
     sCameraService->removeByClient(this);
     sCameraService->logDisconnected(mCameraIdStr, mClientPid,
             String8(mClientPackageName));
+    sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
+            mCameraIdStr.c_str());
 
     sp<IBinder> remote = getRemote();
     if (remote != nullptr) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 064863f..d332f6e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -536,6 +536,7 @@
         void onUidGone(uid_t uid, bool disabled);
         void onUidActive(uid_t uid);
         void onUidIdle(uid_t uid, bool disabled);
+        void onUidStateChanged(uid_t uid __unused, int32_t procState __unused, int64_t procStateSeq __unused) {}
 
         void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
         void removeOverrideUid(uid_t uid, String16 callingPackage);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6da05c3..c1a4c11 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -27,6 +27,8 @@
 #include <camera/CameraUtils.h>
 
 #include "common/CameraDeviceBase.h"
+#include "device3/Camera3Device.h"
+#include "device3/Camera3OutputStream.h"
 #include "api2/CameraDeviceClient.h"
 
 #include <camera_metadata_hidden.h>
@@ -471,6 +473,68 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
+    res = checkOperatingModeLocked(operatingMode);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    status_t err = mDevice->configureStreams(sessionParams, operatingMode);
+    if (err == BAD_VALUE) {
+        String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
+                mCameraIdStr.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    } else if (err != OK) {
+        String8 msg = String8::format("Camera %s: Error configuring streams: %s (%d)",
+                mCameraIdStr.string(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+    }
+
+    return res;
+}
+
+binder::Status CameraDeviceClient::checkSurfaceTypeLocked(size_t numBufferProducers,
+        bool deferredConsumer, int surfaceType) const {
+    if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
+        ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
+                __FUNCTION__, numBufferProducers, MAX_SURFACES_PER_STREAM);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
+    } else if ((numBufferProducers == 0) && (!deferredConsumer)) {
+        ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "No valid consumers.");
+    }
+
+    bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
+            (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
+
+    if (deferredConsumer && !validSurfaceType) {
+        ALOGE("%s: Target surface has invalid surfaceType = %d.", __FUNCTION__, surfaceType);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
+    }
+
+    return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::checkPhysicalCameraIdLocked(String8 physicalCameraId) {
+    if (physicalCameraId.size() > 0) {
+        std::vector<std::string> physicalCameraIds;
+        bool logicalCamera =
+            mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
+        if (!logicalCamera ||
+                std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
+                    physicalCameraId.string()) == physicalCameraIds.end()) {
+            String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+                    mCameraIdStr.string(), physicalCameraId.string());
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+    }
+
+    return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::checkOperatingModeLocked(int operatingMode) const {
     if (operatingMode < 0) {
         String8 msg = String8::format(
             "Camera %s: Invalid operating mode %d requested", mCameraIdStr.string(), operatingMode);
@@ -479,7 +543,6 @@
                 msg.string());
     }
 
-    // Sanitize the high speed session against necessary capability bit.
     bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
     if (isConstrainedHighSpeed) {
         CameraMetadata staticInfo = mDevice->info();
@@ -502,17 +565,163 @@
         }
     }
 
-    status_t err = mDevice->configureStreams(sessionParams, operatingMode);
-    if (err == BAD_VALUE) {
-        String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
-                mCameraIdStr.string());
+    return binder::Status::ok();
+}
+
+void CameraDeviceClient::mapStreamInfo(const OutputStreamInfo &streamInfo,
+            camera3_stream_rotation_t rotation, String8 physicalId,
+            hardware::camera::device::V3_4::Stream *stream /*out*/) {
+    if (stream == nullptr) {
+        return;
+    }
+
+    stream->v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
+    stream->v3_2.width = streamInfo.width;
+    stream->v3_2.height = streamInfo.height;
+    stream->v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
+    auto u = streamInfo.consumerUsage;
+    camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
+    stream->v3_2.usage = Camera3Device::mapToConsumerUsage(u);
+    stream->v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
+    stream->v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
+    stream->physicalCameraId = std::string(physicalId.string());
+    stream->bufferSize = 0;
+}
+
+binder::Status CameraDeviceClient::isSessionConfigurationSupported(
+        const SessionConfiguration& sessionConfiguration, bool *status /*out*/) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    auto operatingMode = sessionConfiguration.getOperatingMode();
+    res = checkOperatingModeLocked(operatingMode);
+    if (!res.isOk()) {
+        return res;
+    }
+
+    if (status == nullptr) {
+        String8 msg = String8::format( "Camera %s: Invalid status!", mCameraIdStr.string());
         ALOGE("%s: %s", __FUNCTION__, msg.string());
-        res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-    } else if (err != OK) {
-        String8 msg = String8::format("Camera %s: Error configuring streams: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+    auto ret = Camera3Device::mapToStreamConfigurationMode(
+            static_cast<camera3_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)", mCameraIdStr.string(),
+            operatingMode, strerror(-ret), ret);
         ALOGE("%s: %s", __FUNCTION__, msg.string());
-        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, 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) {
+        streamConfiguration.streams[streamIdx++] = {{/*streamId*/0,
+                hardware::camera::device::V3_2::StreamType::INPUT,
+                static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
+                static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
+                Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
+                /*usage*/ 0, HAL_DATASPACE_UNKNOWN,
+                hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
+                /*physicalId*/ nullptr, /*bufferSize*/0};
+    }
+
+    for (const auto &it : outputConfigs) {
+        const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
+            it.getGraphicBufferProducers();
+        bool deferredConsumer = it.isDeferred();
+        String8 physicalCameraId = String8(it.getPhysicalCameraId());
+        size_t numBufferProducers = bufferProducers.size();
+        bool isStreamInfoValid = false;
+        OutputStreamInfo streamInfo;
+
+        res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer, it.getSurfaceType());
+        if (!res.isOk()) {
+            return res;
+        }
+
+        res = checkPhysicalCameraIdLocked(physicalCameraId);
+        if (!res.isOk()) {
+            return res;
+        }
+
+        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;
+            }
+            mapStreamInfo(streamInfo, CAMERA3_STREAM_ROTATION_0, physicalCameraId,
+                    &streamConfiguration.streams[streamIdx++]);
+            isStreamInfoValid = true;
+
+            if (numBufferProducers == 0) {
+                continue;
+            }
+        }
+
+        for (auto& bufferProducer : bufferProducers) {
+            sp<Surface> surface;
+            res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
+                    physicalCameraId);
+
+            if (!res.isOk())
+                return res;
+
+            if (!isStreamInfoValid) {
+                mapStreamInfo(streamInfo, static_cast<camera3_stream_rotation_t> (it.getRotation()),
+                        physicalCameraId, &streamConfiguration.streams[streamIdx++]);
+                isStreamInfoValid = true;
+            }
+        }
+    }
+
+    *status = false;
+    ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
+            streamConfiguration, status);
+    switch (ret) {
+        case OK:
+            // Expected, do nothing.
+            break;
+        case INVALID_OPERATION: {
+                String8 msg = String8::format(
+                        "Camera %s: Session configuration query not supported!",
+                        mCameraIdStr.string());
+                ALOGD("%s: %s", __FUNCTION__, msg.string());
+                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+            }
+
+            break;
+        default: {
+                String8 msg = String8::format( "Camera %s: Error: %s (%d)", mCameraIdStr.string(),
+                        strerror(-ret), ret);
+                ALOGE("%s: %s", __FUNCTION__, msg.string());
+                res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        msg.string());
+            }
     }
 
     return res;
@@ -605,40 +814,23 @@
     bool deferredConsumer = outputConfiguration.isDeferred();
     bool isShared = outputConfiguration.isShared();
     String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
-
-    if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
-        ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
-              __FUNCTION__, bufferProducers.size(), MAX_SURFACES_PER_STREAM);
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Surface count is too high");
-    }
     bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
-    int surfaceType = outputConfiguration.getSurfaceType();
-    bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) ||
-            (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE));
 
-    if (deferredConsumer && !validSurfaceType) {
-        ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.",
-                __FUNCTION__, bufferProducers[0].get(), surfaceType);
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid");
+    res = checkSurfaceTypeLocked(numBufferProducers, deferredConsumer,
+            outputConfiguration.getSurfaceType());
+    if (!res.isOk()) {
+        return res;
     }
 
     if (!mDevice.get()) {
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
-    if (physicalCameraId.size() > 0) {
-        std::vector<std::string> physicalCameraIds;
-        bool logicalCamera =
-                mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
-        if (!logicalCamera ||
-                std::find(physicalCameraIds.begin(), physicalCameraIds.end(),
-                physicalCameraId.string()) == physicalCameraIds.end()) {
-            String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
-                    mCameraIdStr.string(), physicalCameraId.string());
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
-        }
+    res = checkPhysicalCameraIdLocked(physicalCameraId);
+    if (!res.isOk()) {
+        return res;
     }
+
     std::vector<sp<Surface>> surfaces;
     std::vector<sp<IBinder>> binders;
     status_t err;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 09ce977..17a0983 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -20,6 +20,7 @@
 #include <android/hardware/camera2/BnCameraDeviceUser.h>
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
 #include <camera/camera2/OutputConfiguration.h>
+#include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
 
 #include "CameraService.h"
@@ -89,6 +90,12 @@
     virtual binder::Status endConfigure(int operatingMode,
             const hardware::camera2::impl::CameraMetadataNative& sessionParams) override;
 
+    // Verify specific session configuration.
+    virtual binder::Status isSessionConfigurationSupported(
+            const SessionConfiguration& sessionConfiguration,
+            /*out*/
+            bool* streamStatus) override;
+
     // Returns -EBUSY if device is not idle or in error state
     virtual binder::Status deleteStream(int streamId) override;
 
@@ -230,6 +237,13 @@
 
     /** Utility members */
     binder::Status checkPidStatus(const char* checkLocation);
+    binder::Status checkOperatingModeLocked(int operatingMode) const;
+    binder::Status checkPhysicalCameraIdLocked(String8 physicalCameraId);
+    binder::Status checkSurfaceTypeLocked(size_t numBufferProducers, bool deferredConsumer,
+            int surfaceType) const;
+    static void mapStreamInfo(const OutputStreamInfo &streamInfo,
+            camera3_stream_rotation_t rotation, String8 physicalId,
+            hardware::camera::device::V3_4::Stream *stream /*out*/);
     bool enforceRequestPermissions(CameraMetadata& metadata);
 
     // Find the square of the euclidean distance between two points
@@ -300,7 +314,7 @@
     // stream ID -> outputStreamInfo mapping
     std::unordered_map<int32_t, OutputStreamInfo> mStreamInfoMap;
 
-    static const int32_t MAX_SURFACES_PER_STREAM = 2;
+    static const int32_t MAX_SURFACES_PER_STREAM = 4;
     sp<CameraProviderManager> mProviderManager;
 };
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 2542ab2..a9cbe72 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -24,23 +24,37 @@
 
 #include <algorithm>
 #include <chrono>
+#include <future>
 #include <inttypes.h>
 #include <hardware/camera_common.h>
 #include <hidl/ServiceManagement.h>
 #include <functional>
 #include <camera_metadata_hidden.h>
 #include <android-base/parseint.h>
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <hwbinder/IPCThreadState.h>
+#include <utils/Trace.h>
 
 namespace android {
 
 using namespace ::android::hardware::camera;
 using namespace ::android::hardware::camera::common::V1_0;
+using std::literals::chrono_literals::operator""s;
 
 namespace {
 // Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
 // service manager
 const std::string kLegacyProviderName("legacy/0");
 const std::string kExternalProviderName("external/0");
+const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+
+// The extra amount of time to hold a reference to an ICameraProvider after it is no longer needed.
+// Hold the reference for this extra time so that if the camera is unreferenced and then referenced
+// again quickly, we do not let the HAL exit and then need to immediately restart it. An example
+// when this could happen is switching from a front-facing to a rear-facing camera. If the HAL were
+// to exit during the camera switch, the camera could appear janky to the user.
+const std::chrono::system_clock::duration kCameraKeepAliveDelay = 3s;
 
 } // anonymous namespace
 
@@ -74,6 +88,8 @@
     addProviderLocked(kLegacyProviderName, /*expected*/ false);
     addProviderLocked(kExternalProviderName, /*expected*/ false);
 
+    IPCThreadState::self()->flushCommands();
+
     return OK;
 }
 
@@ -177,6 +193,19 @@
     return deviceInfo->getCameraInfo(info);
 }
 
+status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
+        const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+        bool *status /*out*/) const {
+    std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+    auto deviceInfo = findDeviceInfoLocked(id);
+    if (deviceInfo == nullptr) {
+        return NAME_NOT_FOUND;
+    }
+
+    return deviceInfo->isSessionConfigurationSupported(configuration, status);
+}
+
 status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
         CameraMetadata* characteristics) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -206,26 +235,15 @@
     return OK;
 }
 
-bool CameraProviderManager::supportSetTorchMode(const std::string &id) {
+bool CameraProviderManager::supportSetTorchMode(const std::string &id) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    bool support = false;
     for (auto& provider : mProviders) {
         auto deviceInfo = findDeviceInfoLocked(id);
         if (deviceInfo != nullptr) {
-            auto ret = provider->mInterface->isSetTorchModeSupported(
-                [&support](auto status, bool supported) {
-                    if (status == Status::OK) {
-                        support = supported;
-                    }
-                });
-            if (!ret.isOk()) {
-                ALOGE("%s: Transaction error checking torch mode support '%s': %s",
-                        __FUNCTION__, provider->mProviderName.c_str(), ret.description().c_str());
-            }
-            break;
+            return provider->mSetTorchModeSupported;
         }
     }
-    return support;
+    return false;
 }
 
 status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled) {
@@ -234,6 +252,15 @@
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
+    // Pass the camera ID to start interface so that it will save it to the map of ICameraProviders
+    // that are currently in use.
+    const sp<provider::V2_4::ICameraProvider> interface =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::TORCH, deviceInfo->mId, interface);
+
     return deviceInfo->setTorchMode(enabled);
 }
 
@@ -241,37 +268,7 @@
     sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
 
     for (auto& provider : mProviders) {
-        hardware::hidl_vec<VendorTagSection> vts;
-        Status status;
-        hardware::Return<void> ret;
-        ret = provider->mInterface->getVendorTags(
-            [&](auto s, const auto& vendorTagSecs) {
-                status = s;
-                if (s == Status::OK) {
-                    vts = vendorTagSecs;
-                }
-        });
-        if (!ret.isOk()) {
-            ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
-                    __FUNCTION__, provider->mProviderName.c_str(), ret.description().c_str());
-            return DEAD_OBJECT;
-        }
-        if (status != Status::OK) {
-            return mapToStatusT(status);
-        }
-
-        // Read all vendor tag definitions into a descriptor
-        sp<VendorTagDescriptor> desc;
-        status_t res;
-        if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/desc))
-                != 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;
-        }
-
-        tagCache->addVendorDescriptor(provider->mProviderTagid, desc);
+        tagCache->addVendorDescriptor(provider->mProviderTagid, provider->mVendorTagDescriptor);
     }
 
     VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
@@ -280,9 +277,9 @@
 }
 
 status_t CameraProviderManager::openSession(const std::string &id,
-        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
+        const sp<device::V3_2::ICameraDeviceCallback>& callback,
         /*out*/
-        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
+        sp<device::V3_2::ICameraDeviceSession> *session) {
 
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
@@ -291,10 +288,22 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
+    const sp<provider::V2_4::ICameraProvider> provider =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::CAMERA, id, provider);
 
     Status status;
     hardware::Return<void> ret;
-    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
+    auto interface = deviceInfo3->startDeviceInterface<
+            CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    ret = interface->open(callback, [&status, &session]
             (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                 status = s;
                 if (status == Status::OK) {
@@ -302,6 +311,7 @@
                 }
             });
     if (!ret.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
         ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                 __FUNCTION__, id.c_str(), ret.description().c_str());
         return DEAD_OBJECT;
@@ -310,9 +320,9 @@
 }
 
 status_t CameraProviderManager::openSession(const std::string &id,
-        const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
+        const sp<device::V1_0::ICameraDeviceCallback>& callback,
         /*out*/
-        sp<hardware::camera::device::V1_0::ICameraDevice> *session) {
+        sp<device::V1_0::ICameraDevice> *session) {
 
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
@@ -321,19 +331,82 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
+    const sp<provider::V2_4::ICameraProvider> provider =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::CAMERA, id, provider);
 
-    hardware::Return<Status> status = deviceInfo1->mInterface->open(callback);
+    auto interface = deviceInfo1->startDeviceInterface<
+            CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    hardware::Return<Status> status = interface->open(callback);
     if (!status.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
         ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                 __FUNCTION__, id.c_str(), status.description().c_str());
         return DEAD_OBJECT;
     }
     if (status == Status::OK) {
-        *session = deviceInfo1->mInterface;
+        *session = interface;
     }
     return mapToStatusT(status);
 }
 
+void CameraProviderManager::saveRef(DeviceMode usageType, const std::string &cameraId,
+        sp<provider::V2_4::ICameraProvider> provider) {
+    if (!kEnableLazyHal) {
+        return;
+    }
+    ALOGI("Saving camera provider %s for camera device %s", provider->descriptor, cameraId.c_str());
+    std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
+    std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *primaryMap, *alternateMap;
+    if (usageType == DeviceMode::TORCH) {
+        primaryMap = &mTorchProviderByCameraId;
+        alternateMap = &mCameraProviderByCameraId;
+    } else {
+        primaryMap = &mCameraProviderByCameraId;
+        alternateMap = &mTorchProviderByCameraId;
+    }
+    auto id = cameraId.c_str();
+    (*primaryMap)[id] = provider;
+    auto search = alternateMap->find(id);
+    if (search != alternateMap->end()) {
+        ALOGW("%s: Camera device %s is using both torch mode and camera mode simultaneously. "
+                "That should not be possible", __FUNCTION__, id);
+    }
+    ALOGV("%s: Camera device %s connected", __FUNCTION__, id);
+}
+
+void CameraProviderManager::removeRef(DeviceMode usageType, const std::string &cameraId) {
+    if (!kEnableLazyHal) {
+        return;
+    }
+    ALOGI("Removing camera device %s", cameraId.c_str());
+    std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *providerMap;
+    if (usageType == DeviceMode::TORCH) {
+        providerMap = &mTorchProviderByCameraId;
+    } else {
+        providerMap = &mCameraProviderByCameraId;
+    }
+    std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
+    auto search = providerMap->find(cameraId.c_str());
+    if (search != providerMap->end()) {
+        auto ptr = search->second;
+        auto future = std::async(std::launch::async, [ptr] {
+            std::this_thread::sleep_for(kCameraKeepAliveDelay);
+            IPCThreadState::self()->flushCommands();
+        });
+        providerMap->erase(cameraId.c_str());
+    } else {
+        ALOGE("%s: Asked to remove reference for camera %s, but no reference to it was found. This "
+                "could mean removeRef was called twice for the same camera ID.", __FUNCTION__,
+                cameraId.c_str());
+    }
+}
 
 hardware::Return<void> CameraProviderManager::onRegistration(
         const hardware::hidl_string& /*fqName*/,
@@ -351,6 +424,8 @@
         listener->onNewProviderRegistered();
     }
 
+    IPCThreadState::self()->flushCommands();
+
     return hardware::Return<void>();
 }
 
@@ -598,9 +673,8 @@
         }
     }
 
-    sp<ProviderInfo> providerInfo =
-            new ProviderInfo(newProvider, interface, this);
-    status_t res = providerInfo->initialize();
+    sp<ProviderInfo> providerInfo = new ProviderInfo(newProvider, this);
+    status_t res = providerInfo->initialize(interface);
     if (res != OK) {
         return res;
     }
@@ -652,27 +726,26 @@
 
 CameraProviderManager::ProviderInfo::ProviderInfo(
         const std::string &providerName,
-        sp<provider::V2_4::ICameraProvider>& interface,
         CameraProviderManager *manager) :
         mProviderName(providerName),
-        mInterface(interface),
         mProviderTagid(generateVendorTagId(providerName)),
         mUniqueDeviceCount(0),
         mManager(manager) {
     (void) mManager;
 }
 
-status_t CameraProviderManager::ProviderInfo::initialize() {
+status_t CameraProviderManager::ProviderInfo::initialize(
+        sp<provider::V2_4::ICameraProvider>& interface) {
     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(), mInterface->isRemote());
+            mProviderName.c_str(), interface->isRemote());
     // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
     // before setCallback returns
-    hardware::Return<Status> status = mInterface->setCallback(this);
+    hardware::Return<Status> status = interface->setCallback(this);
     if (!status.isOk()) {
         ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
                 __FUNCTION__, mProviderName.c_str(), status.description().c_str());
@@ -684,7 +757,7 @@
         return mapToStatusT(status);
     }
 
-    hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
+    hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
     if (!linked.isOk()) {
         ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                 __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
@@ -696,7 +769,7 @@
 
     // Get initial list of camera devices, if any
     std::vector<std::string> devices;
-    hardware::Return<void> ret = mInterface->getCameraIdList([&status, this, &devices](
+    hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
             Status idStatus,
             const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
         status = idStatus;
@@ -725,11 +798,24 @@
         return mapToStatusT(status);
     }
 
+    ret = interface->isSetTorchModeSupported(
+        [this](auto status, bool supported) {
+            if (status == Status::OK) {
+                mSetTorchModeSupported = supported;
+            }
+        });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error checking torch mode support '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+        return DEAD_OBJECT;
+    }
+
+    mIsRemote = interface->isRemote();
+
     sp<StatusListener> listener = mManager->getStatusListener();
     for (auto& device : devices) {
         std::string id;
-        status_t res = addDevice(device,
-                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &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);
@@ -737,13 +823,53 @@
         }
     }
 
+    res = setUpVendorTags();
+    if (res != OK) {
+        ALOGE("%s: Unable to set up vendor tags from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return res;
+    }
+
     ALOGI("Camera provider %s ready with %zu camera devices",
             mProviderName.c_str(), mDevices.size());
 
     mInitialized = true;
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    }
     return OK;
 }
 
+const sp<provider::V2_4::ICameraProvider>
+CameraProviderManager::ProviderInfo::startProviderInterface() {
+    ATRACE_CALL();
+    ALOGI("Request to start camera provider: %s", mProviderName.c_str());
+    if (mSavedInterface != nullptr) {
+        return mSavedInterface;
+    }
+    auto interface = mActiveInterface.promote();
+    if (interface == nullptr) {
+        ALOGI("Could not promote, calling getService(%s)", mProviderName.c_str());
+        interface = mManager->mServiceProxy->getService(mProviderName);
+        interface->setCallback(this);
+        hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
+        if (!linked.isOk()) {
+            ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
+                    __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+            mManager->removeProvider(mProviderName);
+            return nullptr;
+        } else if (!linked) {
+            ALOGW("%s: Unable to link to provider '%s' death notifications",
+                    __FUNCTION__, mProviderName.c_str());
+        }
+        mActiveInterface = interface;
+    } else {
+        ALOGI("Camera provider (%s) already in use. Re-using instance.", mProviderName.c_str());
+    }
+    return interface;
+}
+
 const std::string& CameraProviderManager::ProviderInfo::getType() const {
     return mType;
 }
@@ -825,7 +951,7 @@
 
 status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
     dprintf(fd, "== Camera Provider HAL %s (v2.4, %s) static info: %zu devices: ==\n",
-            mProviderName.c_str(), mInterface->isRemote() ? "remote" : "passthrough",
+            mProviderName.c_str(), mIsRemote ? "remote" : "passthrough",
             mDevices.size());
 
     for (auto& device : mDevices) {
@@ -953,6 +1079,9 @@
                         torchStatusToString(newStatus));
                 id = deviceInfo->mId;
                 known = true;
+                if (TorchModeStatus::AVAILABLE_ON != newStatus) {
+                    mManager->removeRef(DeviceMode::TORCH, id);
+                }
                 break;
             }
         }
@@ -981,15 +1110,55 @@
     mManager->removeProvider(mProviderName);
 }
 
+status_t CameraProviderManager::ProviderInfo::setUpVendorTags() {
+    if (mVendorTagDescriptor != nullptr)
+        return OK;
+
+    hardware::hidl_vec<VendorTagSection> vts;
+    Status status;
+    hardware::Return<void> ret;
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    ret = interface->getVendorTags(
+        [&](auto s, const auto& vendorTagSecs) {
+            status = s;
+            if (s == Status::OK) {
+                vts = vendorTagSecs;
+            }
+    });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+        return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        return mapToStatusT(status);
+    }
+
+    // Read all vendor tag definitions into a descriptor
+    status_t res;
+    if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(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;
+}
+
 template<class DeviceInfoT>
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     CameraProviderManager::ProviderInfo::initializeDeviceInfo(
         const std::string &name, const metadata_vendor_id_t tagId,
-        const std::string &id, uint16_t minorVersion) const {
+        const std::string &id, uint16_t minorVersion) {
     Status status;
 
     auto cameraInterface =
-            getDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
+            startDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
     if (cameraInterface == nullptr) return nullptr;
 
     CameraResourceCost resourceCost;
@@ -1016,13 +1185,13 @@
     }
 
     return std::unique_ptr<DeviceInfo>(
-        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
+        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost, this,
                 mProviderPublicCameraIds, cameraInterface));
 }
 
 template<class InterfaceT>
 sp<InterfaceT>
-CameraProviderManager::ProviderInfo::getDeviceInterface(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface(const std::string &name) {
     ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
             name.c_str(), InterfaceT::version.get_major());
     return nullptr;
@@ -1030,12 +1199,16 @@
 
 template<>
 sp<device::V1_0::ICameraDevice>
-CameraProviderManager::ProviderInfo::getDeviceInterface
-        <device::V1_0::ICameraDevice>(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface
+        <device::V1_0::ICameraDevice>(const std::string &name) {
     Status status;
     sp<device::V1_0::ICameraDevice> cameraInterface;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return nullptr;
+    }
+    ret = interface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
         Status s, sp<device::V1_0::ICameraDevice> interface) {
                 status = s;
                 cameraInterface = interface;
@@ -1055,12 +1228,16 @@
 
 template<>
 sp<device::V3_2::ICameraDevice>
-CameraProviderManager::ProviderInfo::getDeviceInterface
-        <device::V3_2::ICameraDevice>(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface
+        <device::V3_2::ICameraDevice>(const std::string &name) {
     Status status;
     sp<device::V3_2::ICameraDevice> cameraInterface;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return nullptr;
+    }
+    ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
         Status s, sp<device::V3_2::ICameraDevice> interface) {
                 status = s;
                 cameraInterface = interface;
@@ -1081,6 +1258,18 @@
 CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}
 
 template<class InterfaceT>
+sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
+    sp<InterfaceT> device;
+    ATRACE_CALL();
+    if (mSavedInterface == nullptr) {
+        device = mParentProvider->startDeviceInterface<InterfaceT>(mName);
+    } else {
+        device = (InterfaceT *) mSavedInterface.get();
+    }
+    return device;
+}
+
+template<class InterfaceT>
 status_t CameraProviderManager::ProviderInfo::DeviceInfo::setTorchMode(InterfaceT& interface,
         bool enabled) {
     Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
@@ -1091,31 +1280,31 @@
         const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
+        sp<ProviderInfo> parentProvider,
         const std::vector<std::string>& publicCameraIds,
         sp<InterfaceT> interface) :
         DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion},
-                   publicCameraIds, resourceCost),
-        mInterface(interface) {
+                   publicCameraIds, resourceCost, parentProvider) {
     // Get default parameters and initialize flash unit availability
     // Requires powering on the camera device
-    hardware::Return<Status> status = mInterface->open(nullptr);
+    hardware::Return<Status> status = interface->open(nullptr);
     if (!status.isOk()) {
         ALOGE("%s: Transaction error opening camera device %s to check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
         return;
     }
     if (status != Status::OK) {
         ALOGE("%s: Unable to open camera device %s to check for a flash unit: %s", __FUNCTION__,
-                mId.c_str(), CameraProviderManager::statusToString(status));
+                id.c_str(), CameraProviderManager::statusToString(status));
         return;
     }
     hardware::Return<void> ret;
-    ret = mInterface->getParameters([this](const hardware::hidl_string& parms) {
+    ret = interface->getParameters([this](const hardware::hidl_string& parms) {
                 mDefaultParameters.unflatten(String8(parms.c_str()));
             });
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error reading camera device %s params to check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
         return;
     }
     const char *flashMode =
@@ -1124,27 +1313,43 @@
         mHasFlashUnit = true;
     }
 
-    ret = mInterface->close();
+    status_t res = cacheCameraInfo(interface);
+    if (res != OK) {
+        ALOGE("%s: Could not cache CameraInfo", __FUNCTION__);
+        return;
+    }
+
+    ret = interface->close();
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error closing camera device %s after check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
+    }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
     }
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo1::~DeviceInfo1() {}
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo1::setTorchMode(bool enabled) {
-    return DeviceInfo::setTorchMode(mInterface, enabled);
+    return setTorchModeForDevice<InterfaceT>(enabled);
 }
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo1::getCameraInfo(
         hardware::CameraInfo *info) const {
     if (info == nullptr) return BAD_VALUE;
+    *info = mInfo;
+    return OK;
+}
 
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::cacheCameraInfo(
+        sp<CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT> interface) {
     Status status;
     device::V1_0::CameraInfo cInfo;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraInfo([&status, &cInfo](Status s, device::V1_0::CameraInfo camInfo) {
+    ret = interface->getCameraInfo([&status, &cInfo](Status s, device::V1_0::CameraInfo camInfo) {
                 status = s;
                 cInfo = camInfo;
             });
@@ -1159,27 +1364,31 @@
 
     switch(cInfo.facing) {
         case device::V1_0::CameraFacing::BACK:
-            info->facing = hardware::CAMERA_FACING_BACK;
+            mInfo.facing = hardware::CAMERA_FACING_BACK;
             break;
         case device::V1_0::CameraFacing::EXTERNAL:
             // Map external to front for legacy API
         case device::V1_0::CameraFacing::FRONT:
-            info->facing = hardware::CAMERA_FACING_FRONT;
+            mInfo.facing = hardware::CAMERA_FACING_FRONT;
             break;
         default:
             ALOGW("%s: Device %s: Unknown camera facing: %d",
                     __FUNCTION__, mId.c_str(), cInfo.facing);
-            info->facing = hardware::CAMERA_FACING_BACK;
+            mInfo.facing = hardware::CAMERA_FACING_BACK;
     }
-    info->orientation = cInfo.orientation;
+    mInfo.orientation = cInfo.orientation;
 
     return OK;
 }
 
-status_t CameraProviderManager::ProviderInfo::DeviceInfo1::dumpState(int fd) const {
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::dumpState(int fd) {
     native_handle_t* handle = native_handle_create(1,0);
     handle->data[0] = fd;
-    hardware::Return<Status> s = mInterface->dumpState(handle);
+    const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    hardware::Return<Status> s = interface->dumpState(handle);
     native_handle_delete(handle);
     if (!s.isOk()) {
         return INVALID_OPERATION;
@@ -1191,15 +1400,15 @@
         const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
+        sp<ProviderInfo> parentProvider,
         const std::vector<std::string>& publicCameraIds,
         sp<InterfaceT> interface) :
         DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
-                   publicCameraIds, resourceCost),
-        mInterface(interface) {
+                   publicCameraIds, resourceCost, parentProvider) {
     // Get camera characteristics and initialize flash unit availability
     Status status;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraCharacteristics([&status, this](Status s,
+    ret = interface->getCameraCharacteristics([&status, this](Status s,
                     device::V3_2::CameraMetadata metadata) {
                 status = s;
                 if (s == Status::OK) {
@@ -1218,13 +1427,13 @@
             });
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error getting camera characteristics for device %s"
-                " to check for a flash unit: %s", __FUNCTION__, mId.c_str(),
+                " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
                 ret.description().c_str());
         return;
     }
     if (status != Status::OK) {
         ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
-                __FUNCTION__, mId.c_str(), CameraProviderManager::statusToString(status), status);
+                __FUNCTION__, id.c_str(), CameraProviderManager::statusToString(status), status);
         return;
     }
     status_t res = fixupMonochromeTags();
@@ -1244,12 +1453,12 @@
 
     queryPhysicalCameraIds();
     // Get physical camera characteristics if applicable
-    auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface);
+    auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
     if (!castResult.isOk()) {
         ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
         return;
     }
-    sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
+    sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
     if (interface_3_5 == nullptr) {
         ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
         return;
@@ -1283,7 +1492,7 @@
 
             if (!ret.isOk()) {
                 ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
-                        __FUNCTION__, id.c_str(), mId.c_str(), ret.description().c_str());
+                        __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
                 return;
             }
             if (status != Status::OK) {
@@ -1294,12 +1503,17 @@
             }
         }
     }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    }
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
-    return DeviceInfo::setTorchMode(mInterface, enabled);
+    return setTorchModeForDevice<InterfaceT>(enabled);
 }
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
@@ -1350,10 +1564,14 @@
     return isBackwardCompatible;
 }
 
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) const {
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) {
     native_handle_t* handle = native_handle_create(1,0);
     handle->data[0] = fd;
-    auto ret = mInterface->dumpState(handle);
+    const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto ret = interface->dumpState(handle);
     native_handle_delete(handle);
     if (!ret.isOk()) {
         return INVALID_OPERATION;
@@ -1381,6 +1599,49 @@
     return OK;
 }
 
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
+        const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+        bool *status /*out*/) {
+
+    const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
+            this->startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
+    sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
+    if (interface_3_5 == nullptr) {
+        return INVALID_OPERATION;
+    }
+
+    status_t res;
+    Status callStatus;
+    auto ret =  interface_3_5->isStreamCombinationSupported(configuration,
+            [&callStatus, &status] (Status s, bool combStatus) {
+                callStatus = s;
+                *status = combStatus;
+            });
+    if (ret.isOk()) {
+        switch (callStatus) {
+            case Status::OK:
+                // Expected case, do nothing.
+                res = OK;
+                break;
+            case Status::METHOD_NOT_SUPPORTED:
+                res = INVALID_OPERATION;
+                break;
+            default:
+                ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
+                res = UNKNOWN_ERROR;
+        }
+    } else {
+        ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+        res = UNKNOWN_ERROR;
+    }
+
+    return res;
+}
+
 status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name,
         std::string *type, uint32_t *id) {
     // Format must be "<type>/<id>"
@@ -1623,7 +1884,7 @@
 
 
 status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
-        const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
+        const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
         /*out*/
         sp<VendorTagDescriptor>& descriptor) {
 
@@ -1651,7 +1912,7 @@
 
     int idx = 0;
     for (size_t s = 0; s < vts.size(); s++) {
-        const hardware::camera::common::V1_0::VendorTagSection& section = vts[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);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index c506d35..0966743 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
 
 #include <vector>
+#include <unordered_map>
 #include <unordered_set>
 #include <string>
 #include <mutex>
@@ -28,6 +29,7 @@
 #include <utils/Errors.h>
 #include <android/hardware/camera/common/1.0/types.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 //#include <android/hardware/camera/provider/2.4/ICameraProviderCallbacks.h>
 #include <android/hidl/manager/1.0/IServiceNotification.h>
 #include <camera/VendorTagDescriptor.h>
@@ -110,6 +112,14 @@
     };
 
     /**
+     * Represents the mode a camera device is currently in
+     */
+    enum class DeviceMode {
+        TORCH,
+        CAMERA
+    };
+
+    /**
      * Initialize the manager and give it a status listener; optionally accepts a service
      * interaction proxy.
      *
@@ -166,6 +176,13 @@
             CameraMetadata* characteristics) const;
 
     /**
+     * Check for device support of specific stream combination.
+     */
+    status_t isSessionConfigurationSupported(const std::string& id,
+            const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+            bool *status /*out*/) const;
+
+    /**
      * Return the highest supported device interface version for this ID
      */
     status_t getHighestSupportedVersion(const std::string &id,
@@ -174,7 +191,7 @@
     /**
      * Check if a given camera device support setTorchMode API.
      */
-    bool supportSetTorchMode(const std::string &id);
+    bool supportSetTorchMode(const std::string &id) const;
 
     /**
      * Turn on or off the flashlight on a given camera device.
@@ -205,6 +222,17 @@
             sp<hardware::camera::device::V1_0::ICameraDevice> *session);
 
     /**
+     * Save the ICameraProvider while it is being used by a camera or torch client
+     */
+    void saveRef(DeviceMode usageType, const std::string &cameraId,
+            sp<hardware::camera::provider::V2_4::ICameraProvider> provider);
+
+    /**
+     * Notify that the camera or torch is no longer being used by a camera client
+     */
+    void removeRef(DeviceMode usageType, const std::string &cameraId);
+
+    /**
      * IServiceNotification::onRegistration
      * Invoked by the hardware service manager when a new camera provider is registered
      */
@@ -251,20 +279,43 @@
 
     static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;
 
+    // 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
+    std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+            mCameraProviderByCameraId;
+
+    // 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 torch
+    // capabilities
+    std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+            mTorchProviderByCameraId;
+
+    // Lock for accessing mCameraProviderByCameraId and mTorchProviderByCameraId
+    std::mutex mProviderInterfaceMapLock;
+
     struct ProviderInfo :
             virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
             virtual public hardware::hidl_death_recipient
     {
         const std::string mProviderName;
-        const sp<hardware::camera::provider::V2_4::ICameraProvider> mInterface;
         const metadata_vendor_id_t mProviderTagid;
+        sp<VendorTagDescriptor> mVendorTagDescriptor;
+        bool mSetTorchModeSupported;
+        bool mIsRemote;
+
+        // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
+        wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
+
+        sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
 
         ProviderInfo(const std::string &providerName,
-                sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
                 CameraProviderManager *manager);
         ~ProviderInfo();
 
-        status_t initialize();
+        status_t initialize(sp<hardware::camera::provider::V2_4::ICameraProvider>& interface);
+
+        const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
 
         const std::string& getType() const;
 
@@ -286,6 +337,11 @@
         // hidl_death_recipient interface - this locks the parent mInterfaceMutex
         virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
 
+        /**
+         * Setup vendor tags for this provider
+         */
+        status_t setUpVendorTags();
+
         // Basic device information, common to all camera devices
         struct DeviceInfo {
             const std::string mName;  // Full instance name
@@ -294,16 +350,20 @@
             const metadata_vendor_id_t mProviderTagid;
             bool mIsLogicalCamera;
             std::vector<std::string> mPhysicalIds;
+            hardware::CameraInfo mInfo;
+            sp<IBase> mSavedInterface;
 
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
             hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
 
+            sp<ProviderInfo> mParentProvider;
+
             bool hasFlashUnit() const { return mHasFlashUnit; }
             virtual status_t setTorchMode(bool enabled) = 0;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
             virtual bool isAPI1Compatible() const = 0;
-            virtual status_t dumpState(int fd) const = 0;
+            virtual status_t dumpState(int fd) = 0;
             virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
                 (void) characteristics;
                 return INVALID_OPERATION;
@@ -315,14 +375,25 @@
                 return INVALID_OPERATION;
             }
 
+            virtual status_t isSessionConfigurationSupported(
+                    const hardware::camera::device::V3_4::StreamConfiguration &/*configuration*/,
+                    bool * /*status*/) {
+                return INVALID_OPERATION;
+            }
+
+            template<class InterfaceT>
+            sp<InterfaceT> startDeviceInterface();
+
             DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, const hardware::hidl_version& version,
                     const std::vector<std::string>& publicCameraIds,
-                    const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
+                    const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider) :
                     mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
                     mIsLogicalCamera(false), mResourceCost(resourceCost),
                     mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
-                    mHasFlashUnit(false), mPublicCameraIds(publicCameraIds) {}
+                    mParentProvider(parentProvider), mHasFlashUnit(false),
+                    mPublicCameraIds(publicCameraIds) {}
             virtual ~DeviceInfo();
         protected:
             bool mHasFlashUnit;
@@ -330,6 +401,14 @@
 
             template<class InterfaceT>
             static status_t setTorchMode(InterfaceT& interface, bool enabled);
+
+            template<class InterfaceT>
+            status_t setTorchModeForDevice(bool enabled) {
+                // Don't save the ICameraProvider interface here because we assume that this was
+                // called from CameraProviderManager::setTorchMode(), which does save it.
+                const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+                return DeviceInfo::setTorchMode(interface, enabled);
+            }
         };
         std::vector<std::unique_ptr<DeviceInfo>> mDevices;
         std::unordered_set<std::string> mUniqueCameraIds;
@@ -345,40 +424,45 @@
         // HALv1-specific camera fields, including the actual device interface
         struct DeviceInfo1 : public DeviceInfo {
             typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
-            const sp<InterfaceT> mInterface;
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
             //In case of Device1Info assume that we are always API1 compatible
             virtual bool isAPI1Compatible() const override { return true; }
-            virtual status_t dumpState(int fd) const override;
+            virtual status_t dumpState(int fd) override;
             DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider,
                     const std::vector<std::string>& publicCameraIds,
                     sp<InterfaceT> interface);
             virtual ~DeviceInfo1();
         private:
             CameraParameters2 mDefaultParameters;
+            status_t cacheCameraInfo(sp<InterfaceT> interface);
         };
 
         // HALv3-specific camera fields, including the actual device interface
         struct DeviceInfo3 : public DeviceInfo {
             typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
-            const sp<InterfaceT> mInterface;
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
             virtual bool isAPI1Compatible() const override;
-            virtual status_t dumpState(int fd) const override;
+            virtual status_t dumpState(int fd) override;
             virtual status_t getCameraCharacteristics(
                     CameraMetadata *characteristics) const override;
             virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
                     CameraMetadata *characteristics) const override;
+            virtual status_t isSessionConfigurationSupported(
+                    const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+                    bool *status /*out*/)
+                    override;
 
             DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider,
                     const std::vector<std::string>& publicCameraIds, sp<InterfaceT> interface);
             virtual ~DeviceInfo3();
         private:
@@ -405,11 +489,11 @@
         template<class DeviceInfoT>
         std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
                 const metadata_vendor_id_t tagId, const std::string &id,
-                uint16_t minorVersion) const;
+                uint16_t minorVersion);
 
         // Helper for initializeDeviceInfo to use the right CameraProvider get method.
         template<class InterfaceT>
-        sp<InterfaceT> getDeviceInterface(const std::string &name) const;
+        sp<InterfaceT> startDeviceInterface(const std::string &name);
 
         // Parse provider instance name for type and id
         static status_t parseProviderName(const std::string& name,
@@ -443,6 +527,14 @@
 
     std::vector<sp<ProviderInfo>> mProviders;
 
+    void addProviderToMap(
+            const std::string &cameraId,
+            sp<hardware::camera::provider::V2_4::ICameraProvider> provider,
+            bool isTorchUsage);
+    void removeCameraIdFromMap(
+        std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>> &map,
+        const std::string &cameraId);
+
     static const char* deviceStatusToString(
         const hardware::camera::common::V1_0::CameraDeviceStatus&);
     static const char* torchStatusToString(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 419ac42..e5a38bb 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -194,6 +194,28 @@
      */
     status_t dropStreamBuffers(bool dropping, int streamId) override;
 
+    /**
+     * Helper functions to map between framework and HIDL values
+     */
+    static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
+    static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
+            android_dataspace dataSpace);
+    static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
+    static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
+            camera3_stream_rotation_t rotation);
+    // Returns a negative error code if the passed-in operation mode is not valid.
+    static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
+            /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
+    static camera3_buffer_status_t mapHidlBufferStatus(
+            hardware::camera::device::V3_2::BufferStatus status);
+    static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
+    static android_dataspace mapToFrameworkDataspace(
+            hardware::camera::device::V3_2::DataspaceFlags);
+    static uint64_t mapConsumerToFrameworkUsage(
+            hardware::camera::device::V3_2::BufferUsageFlags usage);
+    static uint64_t mapProducerToFrameworkUsage(
+            hardware::camera::device::V3_2::BufferUsageFlags usage);
+
   private:
 
     status_t disconnectImpl();
@@ -679,27 +701,6 @@
      */
     static nsecs_t getMonoToBoottimeOffset();
 
-    /**
-     * Helper functions to map between framework and HIDL values
-     */
-    static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
-    static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
-            android_dataspace dataSpace);
-    static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
-    static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
-            camera3_stream_rotation_t rotation);
-    // Returns a negative error code if the passed-in operation mode is not valid.
-    static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
-            /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
-    static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
-    static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
-    static android_dataspace mapToFrameworkDataspace(
-            hardware::camera::device::V3_2::DataspaceFlags);
-    static uint64_t mapConsumerToFrameworkUsage(
-            hardware::camera::device::V3_2::BufferUsageFlags usage);
-    static uint64_t mapProducerToFrameworkUsage(
-            hardware::camera::device::V3_2::BufferUsageFlags usage);
-
     struct RequestTrigger {
         // Metadata tag number, e.g. android.control.aePrecaptureTrigger
         uint32_t metadataTag;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 219cc24..8cd575d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -663,12 +663,11 @@
     return res;
 }
 
-status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
-        const sp<Surface>& surface) const {
-    status_t res;
-    uint64_t u = 0;
+void Camera3OutputStream::applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/) {
+    if (consumerUsage == nullptr) {
+        return;
+    }
 
-    res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
     // If an opaque output stream's endpoint is ImageReader, add
     // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
     // for the ZSL use case.
@@ -677,12 +676,20 @@
     //     2. GRALLOC_USAGE_HW_RENDER
     //     3. GRALLOC_USAGE_HW_COMPOSER
     //     4. GRALLOC_USAGE_HW_VIDEO_ENCODER
-    if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
-            (u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
+    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+            (*consumerUsage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
             GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) {
-        u |= GRALLOC_USAGE_HW_CAMERA_ZSL;
+        *consumerUsage |= GRALLOC_USAGE_HW_CAMERA_ZSL;
     }
+}
 
+status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
+        const sp<Surface>& surface) const {
+    status_t res;
+    uint64_t u = 0;
+
+    res = native_window_get_consumer_usage(static_cast<ANativeWindow*>(surface.get()), &u);
+    applyZSLUsageQuirk(camera3_stream::format, &u);
     *usage = u;
     return res;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 410905d..2128da2 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -201,6 +201,11 @@
             const std::vector<size_t> &removedSurfaceIds,
             KeyedVector<sp<Surface>, size_t> *outputMap/*out*/);
 
+    /**
+     * Apply ZSL related consumer usage quirk.
+     */
+    static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
+
   protected:
     Camera3OutputStream(int id, camera3_stream_type_t type,
             uint32_t width, uint32_t height, int format,
diff --git a/services/camera/libcameraservice/hidl/Convert.cpp b/services/camera/libcameraservice/hidl/Convert.cpp
index 76ed6f6..582ce34 100644
--- a/services/camera/libcameraservice/hidl/Convert.cpp
+++ b/services/camera/libcameraservice/hidl/Convert.cpp
@@ -101,12 +101,14 @@
 bool convertFromHidl(const HCameraMetadata &src, CameraMetadata *dst) {
     const camera_metadata_t *buffer = reinterpret_cast<const camera_metadata_t*>(src.data());
     size_t expectedSize = src.size();
-    int res = validate_camera_metadata_structure(buffer, &expectedSize);
-    if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
-        *dst = buffer;
-    } else {
-        ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
-        return false;
+    if (buffer != nullptr) {
+        int res = validate_camera_metadata_structure(buffer, &expectedSize);
+        if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+            *dst = buffer;
+        } else {
+            ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+            return false;
+        }
     }
     return true;
 }
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index 8d80ff1..ad9963a 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -30,7 +30,8 @@
     android.hardware.camera.common@1.0 \
     android.hardware.camera.provider@2.4 \
     android.hardware.camera.device@1.0 \
-    android.hardware.camera.device@3.2
+    android.hardware.camera.device@3.2 \
+    android.hardware.camera.device@3.4
 
 LOCAL_C_INCLUDES += \
     system/media/private/camera/include \
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
new file mode 100644
index 0000000..653317b
--- /dev/null
+++ b/services/mediacodec/registrant/Android.bp
@@ -0,0 +1,53 @@
+cc_library_shared {
+    name: "libmedia_codecserviceregistrant",
+    srcs: [
+        "CodecServiceRegistrant.cpp",
+    ],
+
+    header_libs: [
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "libbase",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libutils",
+    ],
+
+    // Codecs
+    runtime_libs: [
+        "libcodec2_soft_avcdec",
+        "libcodec2_soft_avcenc",
+        "libcodec2_soft_aacdec",
+        "libcodec2_soft_aacenc",
+        "libcodec2_soft_amrnbdec",
+        "libcodec2_soft_amrnbenc",
+        "libcodec2_soft_amrwbdec",
+        "libcodec2_soft_amrwbenc",
+        "libcodec2_soft_hevcdec",
+        "libcodec2_soft_g711alawdec",
+        "libcodec2_soft_g711mlawdec",
+        "libcodec2_soft_mpeg2dec",
+        "libcodec2_soft_h263dec",
+        "libcodec2_soft_h263enc",
+        "libcodec2_soft_mpeg4dec",
+        "libcodec2_soft_mpeg4enc",
+        "libcodec2_soft_mp3dec",
+        "libcodec2_soft_vorbisdec",
+        "libcodec2_soft_opusdec",
+        "libcodec2_soft_vp8dec",
+        "libcodec2_soft_vp9dec",
+        "libcodec2_soft_vp8enc",
+        "libcodec2_soft_vp9enc",
+        "libcodec2_soft_rawdec",
+        "libcodec2_soft_flacdec",
+        "libcodec2_soft_flacenc",
+        "libcodec2_soft_gsmdec",
+        "libcodec2_soft_xaacdec",
+    ],
+
+    compile_multilib: "32",
+}
+
diff --git a/media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
similarity index 74%
rename from media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp
rename to services/mediacodec/registrant/CodecServiceRegistrant.cpp
index e10ae6e..706ebee 100644
--- a/media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -15,26 +15,30 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "C2SoftwareCodecServiceRegistrant"
+#define LOG_TAG "CodecServiceRegistrant"
+
+#include <android-base/logging.h>
 
 #include <C2PlatformSupport.h>
 #include <codec2/hidl/1.0/ComponentStore.h>
 #include <media/CodecServiceRegistrant.h>
-#include <log/log.h>
 
 extern "C" void RegisterCodecServices() {
     using namespace ::android::hardware::media::c2::V1_0;
+    LOG(INFO) << "Creating software Codec2 service...";
     android::sp<IComponentStore> store =
         new utils::ComponentStore(
                 android::GetCodec2PlatformComponentStore());
     if (store == nullptr) {
-        ALOGE("Cannot create Codec2's IComponentStore software service.");
+        LOG(ERROR) <<
+                "Cannot create software Codec2 service.";
     } else {
         if (store->registerAsService("software") != android::OK) {
-            ALOGE("Cannot register Codec2's "
-                    "IComponentStore software service.");
+            LOG(ERROR) <<
+                    "Cannot register software Codec2 service.";
         } else {
-            ALOGI("Codec2's IComponentStore software service created.");
+            LOG(INFO) <<
+                    "Software Codec2 service created.";
         }
     }
 }
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 73c9535..19ce7e9 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -9,6 +9,24 @@
 
 LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
 LOCAL_MODULE:= libmediaextractorservice
+
+sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
+  $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(UBSAN_RUNTIME_LIBRARY) \
+  $(TSAN_RUNTIME_LIBRARY)))
+
+# $(info Sanitizer:  $(sanitizer_runtime_libraries))
+
+ndk_libraries := $(call normalize-path-list,$(addprefix lib,$(addsuffix .so,\
+  $(NDK_PREBUILT_SHARED_LIBRARIES))))
+
+# $(info NDK:  $(ndk_libraries))
+
+LOCAL_CFLAGS += -DLINKED_LIBRARIES='"$(sanitizer_runtime_libraries):$(ndk_libraries)"'
+
+sanitizer_runtime_libraries :=
+ndk_libraries :=
+
 include $(BUILD_SHARED_LIBRARY)
 
 
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index f4d8b43..8b26178 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -29,6 +29,11 @@
 
 namespace android {
 
+MediaExtractorService::MediaExtractorService()
+        : BnMediaExtractorService() {
+    MediaExtractorFactory::SetLinkedLibraries(std::string(LINKED_LIBRARIES));
+}
+
 sp<IMediaExtractor> MediaExtractorService::makeExtractor(
         const sp<IDataSource> &remoteSource, const char *mime) {
     ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime);
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 9df3ecd..6007004 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -27,7 +27,7 @@
 {
     friend class BinderService<MediaExtractorService>;    // for MediaExtractorService()
 public:
-    MediaExtractorService() : BnMediaExtractorService() { }
+    MediaExtractorService();
     virtual ~MediaExtractorService() { }
     virtual void onFirstRef() { }
 
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index b1854bf..cca1895 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -172,7 +172,7 @@
 
         aaudio_result_t result = endpoint->open(request);
         if (result != AAUDIO_OK) {
-            ALOGE("openExclusiveEndpoint(), open failed");
+            ALOGV("openExclusiveEndpoint(), open failed");
             endpoint.clear();
         } else {
             mExclusiveStreams.push_back(endpointMMap);
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 5ec997c..2fbaeb4 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -118,7 +118,7 @@
         }
     }
 
-    // If SHARED requested or if EXCLUSIVE failed.
+    // Try SHARED if SHARED requested or if EXCLUSIVE failed.
     if (sharingMode == AAUDIO_SHARING_MODE_SHARED) {
         serviceStream =  new AAudioServiceStreamShared(*this);
         result = serviceStream->open(request);
@@ -132,8 +132,7 @@
 
     if (result != AAUDIO_OK) {
         serviceStream.clear();
-        ALOGE("openStream(): failed, return %d = %s",
-              result, AAudio_convertResultToText(result));
+        ALOGW("openStream(): failed, return %d = %s", result, AAudio_convertResultToText(result));
         return result;
     } else {
         aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 24ab65e..539735a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -38,10 +38,6 @@
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
 
-AAudioServiceEndpoint::~AAudioServiceEndpoint() {
-    ALOGD("%s(%p) destroyed", __func__, this);
-}
-
 std::string AAudioServiceEndpoint::dump() const {
     std::stringstream result;
 
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a134a13..43b0a37 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -41,7 +41,7 @@
         , public AAudioStreamParameters {
 public:
 
-    virtual ~AAudioServiceEndpoint();
+    virtual ~AAudioServiceEndpoint() = default;
 
     virtual std::string dump() const;
 
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 18fcd35..e4dbee1 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -101,8 +101,6 @@
             .flags = AUDIO_FLAG_LOW_LATENCY,
             .tags = ""
     };
-    ALOGD("%s(%p) MMAP attributes.usage = %d, content_type = %d, source = %d",
-          __func__, this, attributes.usage, attributes.content_type, attributes.source);
 
     mMmapClient.clientUid = request.getUserId();
     mMmapClient.clientPid = request.getProcessId();
@@ -163,12 +161,12 @@
     ALOGD("%s() mMapClient.uid = %d, pid = %d => portHandle = %d\n",
           __func__, mMmapClient.clientUid,  mMmapClient.clientPid, mPortHandle);
     if (status != OK) {
-        ALOGE("%s() openMmapStream() returned status %d",  __func__, status);
+        ALOGE("%s() - openMmapStream() returned status %d",  __func__, status);
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
     if (deviceId == AAUDIO_UNSPECIFIED) {
-        ALOGW("%s() openMmapStream() failed to set deviceId", __func__);
+        ALOGW("%s() - openMmapStream() failed to set deviceId", __func__);
     }
     setDeviceId(deviceId);
 
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index a274466..923a1a4 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -47,10 +47,6 @@
     mStreamInternal = &mStreamInternalPlay;
 }
 
-AAudioServiceEndpointPlay::~AAudioServiceEndpointPlay() {
-    ALOGD("%s(%p) destroyed", __func__, this);
-}
-
 aaudio_result_t AAudioServiceEndpointPlay::open(const aaudio::AAudioStreamRequest &request) {
     aaudio_result_t result = AAudioServiceEndpointShared::open(request);
     if (result == AAUDIO_OK) {
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.h b/services/oboeservice/AAudioServiceEndpointPlay.h
index a0a383c..981e430 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.h
+++ b/services/oboeservice/AAudioServiceEndpointPlay.h
@@ -39,7 +39,6 @@
 class AAudioServiceEndpointPlay : public AAudioServiceEndpointShared {
 public:
     explicit AAudioServiceEndpointPlay(android::AAudioService &audioService);
-    virtual ~AAudioServiceEndpointPlay();
 
     aaudio_result_t open(const aaudio::AAudioStreamRequest &request) override;
 
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index d671710..bfc1744 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -52,8 +52,7 @@
 
     aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
 
-    virtual void            *callbackLoop() = 0;
-
+    virtual void   *callbackLoop() = 0;
 
 protected:
 
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 12be4a3..354b36a 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -51,7 +51,6 @@
 }
 
 AAudioServiceStreamBase::~AAudioServiceStreamBase() {
-    ALOGD("~AAudioServiceStreamBase() destroying %p", this);
     // If the stream is deleted when OPEN or in use then audio resources will leak.
     // This would indicate an internal error. So we want to find this ASAP.
     LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
@@ -110,7 +109,6 @@
         mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService,
                                                          request);
         if (mServiceEndpoint == nullptr) {
-            ALOGE("%s() openEndpoint() failed", __func__);
             result = AAUDIO_ERROR_UNAVAILABLE;
             goto error;
         }
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index dbc2c2e..d5450fe 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -128,7 +128,6 @@
 
     aaudio_result_t result = AAudioServiceStreamBase::open(request);
     if (result != AAUDIO_OK) {
-        ALOGE("%s() returned %d", __func__, result);
         return result;
     }