Merge "AML: Replace ParceledListSlice"
diff --git a/apex/Android.bp b/apex/Android.bp
index eee26ae..05cc2c5 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -21,7 +21,11 @@
         "libamrextractor",
         "libflacextractor",
         "libmidiextractor",
+        "libmkvextractor",
         "libmp3extractor",
+        "libmp4extractor",
+        "libmpeg2extractor",
+        "liboggextractor",
         "libwavextractor",
     ],
     key: "com.android.media.key",
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 00da54e..657d41f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -633,7 +633,7 @@
     }
 
     std::set<std::pair<ANativeWindow*, OutputConfiguration>> outputSet;
-    for (auto outConfig : outputs->mOutputs) {
+    for (const auto& outConfig : outputs->mOutputs) {
         ANativeWindow* anw = outConfig.mWindow;
         sp<IGraphicBufferProducer> iGBP(nullptr);
         ret = getIGBPfromAnw(anw, iGBP);
@@ -706,7 +706,7 @@
     }
 
     // add new streams
-    for (auto outputPair : addSet) {
+    for (const auto& outputPair : addSet) {
         int streamId;
         remoteRet = mRemote->createStream(outputPair.second, &streamId);
         if (!remoteRet.isOk()) {
@@ -839,7 +839,7 @@
 
         const auto& gbps = outputPairIt->second.second.getGraphicBufferProducers();
         for (const auto& outGbp : gbps) {
-            for (auto surface : request->mSurfaceList) {
+            for (const auto& surface : request->mSurfaceList) {
                 if (surface->getIGraphicBufferProducer() == outGbp) {
                     ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
                     ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index c7619af..7a10302 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -191,7 +191,6 @@
 LOCAL_MODULE:= mediafilter
 
 LOCAL_SANITIZE := cfi
-LOCAL_SANITIZE_DIAG := cfi
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 94f9e02..41d1833 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -73,7 +73,6 @@
         // Suppress unused parameter and no error options. These cause problems
         // with the when using the map type in a proto definition.
         "-Wno-unused-parameter",
-        "-Wno-error",
     ],
 }
 
@@ -106,7 +105,6 @@
         // Suppress unused parameter and no error options. These cause problems
         // when using the map type in a proto definition.
         "-Wno-unused-parameter",
-        "-Wno-error",
     ],
 }
 
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
index dcd59b7..9e0115e 100644
--- a/drm/libmediadrm/tests/Android.bp
+++ b/drm/libmediadrm/tests/Android.bp
@@ -34,7 +34,6 @@
         // Suppress unused parameter and no error options. These cause problems
         // when using the map type in a proto definition.
         "-Wno-unused-parameter",
-        "-Wno-error",
     ]
 }
 
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
index 292ec93..705aa81 100644
--- a/include/media/MediaExtractorPluginHelper.h
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -183,32 +183,32 @@
         mBuffer = buf;
     }
 
-    ~MediaBufferHelperV3() {}
+    virtual ~MediaBufferHelperV3() {}
 
-    void release() {
+    virtual void release() {
         mBuffer->release(mBuffer->handle);
     }
 
-    void* data() {
+    virtual void* data() {
         return mBuffer->data(mBuffer->handle);
     }
 
-    size_t size() {
+    virtual size_t size() {
         return mBuffer->size(mBuffer->handle);
     }
 
-    size_t range_offset() {
+    virtual size_t range_offset() {
         return mBuffer->range_offset(mBuffer->handle);
     }
 
-    size_t range_length() {
+    virtual size_t range_length() {
         return mBuffer->range_length(mBuffer->handle);
     }
 
-    void set_range(size_t offset, size_t length) {
+    virtual void set_range(size_t offset, size_t length) {
         mBuffer->set_range(mBuffer->handle, offset, length);
     }
-    AMediaFormat *meta_data() {
+    virtual AMediaFormat *meta_data() {
         return mBuffer->meta_data(mBuffer->handle);
     }
 };
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 2c734ac..5260909 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -253,9 +253,21 @@
 }
 
 void Accessor::Impl::handleInvalidateAck() {
-    std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
-    mBufferPool.processStatusMessages();
-    mBufferPool.mInvalidation.onHandleAck();
+    std::map<ConnectionId, const sp<IObserver>> observers;
+    uint32_t invalidationId;
+    {
+        std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+        mBufferPool.processStatusMessages();
+        mBufferPool.mInvalidation.onHandleAck(&observers, &invalidationId);
+    }
+    // Do not hold lock for send invalidations
+    for (auto it = observers.begin(); it != observers.end(); ++it) {
+        const sp<IObserver> observer = it->second;
+        if (observer) {
+            Return<void> transResult = observer->onMessage(it->first, invalidationId);
+            (void) transResult;
+        }
+    }
 }
 
 bool Accessor::Impl::isValid() {
@@ -365,19 +377,21 @@
     sInvalidator->addAccessor(mId, impl);
 }
 
-void Accessor::Impl::BufferPool::Invalidation::onHandleAck() {
+void Accessor::Impl::BufferPool::Invalidation::onHandleAck(
+        std::map<ConnectionId, const sp<IObserver>> *observers,
+        uint32_t *invalidationId) {
     if (mInvalidationId != 0) {
+        *invalidationId = mInvalidationId;
         std::set<int> deads;
         for (auto it = mAcks.begin(); it != mAcks.end(); ++it) {
             if (it->second != mInvalidationId) {
                 const sp<IObserver> observer = mObservers[it->first];
                 if (observer) {
-                    ALOGV("connection %lld call observer (%u: %u)",
+                    observers->emplace(it->first, observer);
+                    ALOGV("connection %lld will call observer (%u: %u)",
                           (long long)it->first, it->second, mInvalidationId);
-                    Return<void> transResult = observer->onMessage(it->first, mInvalidationId);
-                    (void) transResult;
-                    // N.B: ignore possibility of onMessage oneway call being
-                    // lost.
+                    // N.B: onMessage will be called later. ignore possibility of
+                    // onMessage# oneway call being lost.
                     it->second = mInvalidationId;
                 } else {
                     ALOGV("bufferpool2 observer died %lld", (long long)it->first);
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index b3faa96..eea72b9 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -158,7 +158,9 @@
                     BufferInvalidationChannel &channel,
                     const std::shared_ptr<Accessor::Impl> &impl);
 
-            void onHandleAck();
+            void onHandleAck(
+                    std::map<ConnectionId, const sp<IObserver>> *observers,
+                    uint32_t *invalidationId);
         } mInvalidation;
         /// Buffer pool statistics which tracks allocation and transfer statistics.
         struct Stats {
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
index 6fd9200..1e87f38 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
@@ -156,63 +156,31 @@
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
-            // handle configuration changes in work done
-            if (!work->worklets.empty() &&
-                (work->worklets.front()->output.configUpdate.size() != 0)) {
-                ALOGV("Config Update");
-                std::vector<std::unique_ptr<C2Param>> updates =
-                    std::move(work->worklets.front()->output.configUpdate);
-                std::vector<C2Param*> configParam;
-                std::vector<std::unique_ptr<C2SettingResult>> failures;
-                for (size_t i = 0; i < updates.size(); ++i) {
-                    C2Param* param = updates[i].get();
-                    if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) ||
-                        (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE)) {
-                        configParam.push_back(param);
+            if (!work->worklets.empty()) {
+                // For decoder components current timestamp always exceeds
+                // previous timestamp
+                bool codecConfig = ((work->worklets.front()->output.flags &
+                                     C2FrameData::FLAG_CODEC_CONFIG) != 0);
+                if (!codecConfig &&
+                    !work->worklets.front()->output.buffers.empty()) {
+                    EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
+                        mTimestampUs);
+                    mTimestampUs =
+                        work->worklets.front()->output.ordinal.timestamp.peeku();
+                    uint32_t rangeLength =
+                        work->worklets.front()->output.buffers[0]->data()
+                        .linearBlocks().front().map().get().capacity();
+                    //List of timestamp values and output size to calculate timestamp
+                    if (mTimestampDevTest) {
+                        outputMetaData meta = {mTimestampUs, rangeLength};
+                        oBufferMetaData.push_back(meta);
                     }
                 }
-                mComponent->config(configParam, C2_DONT_BLOCK, &failures);
-                ASSERT_EQ(failures.size(), 0u);
-            }
-            mFramesReceived++;
-            mEos = (work->worklets.front()->output.flags &
-                    C2FrameData::FLAG_END_OF_STREAM) != 0;
-            auto frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          work->input.ordinal.frameIndex.peeku());
-            ALOGV("WorkDone: frameID received %d",
-                (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
-
-            // For decoder components current timestamp always exceeds
-            // previous timestamp
-            bool codecConfig = ((work->worklets.front()->output.flags &
-                                 C2FrameData::FLAG_CODEC_CONFIG) != 0);
-            if (!codecConfig &&
-                !work->worklets.front()->output.buffers.empty()) {
-                EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
-                    mTimestampUs);
-                mTimestampUs =
-                    work->worklets.front()->output.ordinal.timestamp.peeku();
-                uint32_t rangeLength =
-                    work->worklets.front()->output.buffers[0]->data()
-                    .linearBlocks().front().map().get().capacity();
-                //List of timestamp values and output size to calculate timestamp
-                if (mTimestampDevTest) {
-                    outputMetaData meta = {mTimestampUs, rangeLength};
-                    oBufferMetaData.push_back(meta);
-                }
-            }
-
-            work->input.buffers.clear();
-            work->worklets.clear();
-            {
-                typedef std::unique_lock<std::mutex> ULock;
-                ULock l(mQueueLock);
-                mWorkQueue.push_back(std::move(work));
-                if (!mFlushedIndices.empty()) {
-                    mFlushedIndices.erase(frameIndexIt);
-                }
-                mQueueCondition.notify_all();
+                bool mCsd = false;
+                workDone(mComponent, work, mFlushedIndices, mQueueLock,
+                         mQueueCondition, mWorkQueue, mEos, mCsd,
+                         mFramesReceived);
+                (void)mCsd;
             }
         }
     }
@@ -418,11 +386,11 @@
     }
 }
 
-void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
-                   std::mutex &queueLock, std::condition_variable &queueCondition,
-                   std::list<std::unique_ptr<C2Work>> &workQueue,
-                   std::list<uint64_t> &flushedIndices,
-                   std::shared_ptr<C2BlockPool> &linearPool,
+void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::list<std::unique_ptr<C2Work>>& workQueue,
+                   std::list<uint64_t>& flushedIndices,
+                   std::shared_ptr<C2BlockPool>& linearPool,
                    std::ifstream& eleStream,
                    android::Vector<FrameInfo>* Info,
                    int offset, int range, bool signalEOS = true) {
@@ -462,34 +430,37 @@
         }
         int size = (*Info)[frameID].bytesCount;
         char* data = (char*)malloc(size);
+        ASSERT_NE(data, nullptr);
 
         eleStream.read(data, size);
         ASSERT_EQ(eleStream.gcount(), size);
 
-        std::shared_ptr<C2LinearBlock> block;
-        ASSERT_EQ(C2_OK,
-                  linearPool->fetchLinearBlock(
-                      size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
-                      &block));
-        ASSERT_TRUE(block);
-
-        // Write View
-        C2WriteView view = block->map().get();
-        if (view.error() != C2_OK) {
-            fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
-            break;
-        }
-        ASSERT_EQ((size_t)size, view.capacity());
-        ASSERT_EQ(0u, view.offset());
-        ASSERT_EQ((size_t)size, view.size());
-
-        memcpy(view.base(), data, size);
-
         work->input.buffers.clear();
-        work->input.buffers.emplace_back(new LinearBuffer(block));
+        if (size) {
+            std::shared_ptr<C2LinearBlock> block;
+            ASSERT_EQ(C2_OK,
+                    linearPool->fetchLinearBlock(
+                        size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+                        &block));
+            ASSERT_TRUE(block);
+
+            // Write View
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
+                break;
+            }
+            ASSERT_EQ((size_t)size, view.capacity());
+            ASSERT_EQ(0u, view.offset());
+            ASSERT_EQ((size_t)size, view.size());
+
+            memcpy(view.base(), data, size);
+
+            work->input.buffers.emplace_back(new LinearBuffer(block));
+            free(data);
+        }
         work->worklets.clear();
         work->worklets.emplace_back(new C2Worklet);
-        free(data);
 
         std::list<std::unique_ptr<C2Work>> items;
         items.push_back(std::move(work));
@@ -502,29 +473,6 @@
     }
 }
 
-void waitOnInputConsumption(std::mutex& queueLock,
-                            std::condition_variable& queueCondition,
-                            std::list<std::unique_ptr<C2Work>>& workQueue,
-                            size_t bufferCount = MAX_INPUT_BUFFERS) {
-    typedef std::unique_lock<std::mutex> ULock;
-    uint32_t queueSize;
-    uint32_t maxRetry = 0;
-    {
-        ULock l(queueLock);
-        queueSize = workQueue.size();
-    }
-    while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
-        ULock l(queueLock);
-        if (queueSize != workQueue.size()) {
-            queueSize = workQueue.size();
-            maxRetry = 0;
-        } else {
-            queueCondition.wait_for(l, TIME_OUT);
-            maxRetry++;
-        }
-    }
-}
-
 TEST_F(Codec2AudioDecHidlTest, validateCompName) {
     if (mDisableTest) return;
     ALOGV("Checks if the given component is a valid audio component");
@@ -718,7 +666,6 @@
     ASSERT_EQ(mComponent->queue(&items), C2_OK);
 
     {
-        typedef std::unique_lock<std::mutex> ULock;
         ULock l(mQueueLock);
         if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
             mQueueCondition.wait_for(l, TIME_OUT);
@@ -729,46 +676,6 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2AudioDecHidlTest, EmptyBufferTest) {
-    description("Tests empty input buffer");
-    if (mDisableTest) return;
-    typedef std::unique_lock<std::mutex> ULock;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-    std::unique_ptr<C2Work> work;
-    // Prepare C2Work
-    {
-        ULock l(mQueueLock);
-        if (!mWorkQueue.empty()) {
-            work.swap(mWorkQueue.front());
-            mWorkQueue.pop_front();
-        } else {
-            ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test";
-        }
-    }
-    ASSERT_NE(work, nullptr);
-
-    work->input.flags = (C2FrameData::flags_t)0;
-    work->input.ordinal.timestamp = 0;
-    work->input.ordinal.frameIndex = 0;
-    work->input.buffers.clear();
-    work->worklets.clear();
-    work->worklets.emplace_back(new C2Worklet);
-
-    std::list<std::unique_ptr<C2Work>> items;
-    items.push_back(std::move(work));
-    ASSERT_EQ(mComponent->queue(&items), C2_OK);
-
-    {
-        typedef std::unique_lock<std::mutex> ULock;
-        ULock l(mQueueLock);
-        if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
-            mQueueCondition.wait_for(l, TIME_OUT);
-        }
-    }
-    ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
-    ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
 TEST_F(Codec2AudioDecHidlTest, FlushTest) {
     description("Tests Flush calls");
     if (mDisableTest) return;
@@ -891,6 +798,72 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
+    description("Decode with multiple empty input frames");
+    if (mDisableTest) return;
+
+    ASSERT_EQ(mComponent->start(), C2_OK);
+
+    char mURL[512], info[512];
+    std::ifstream eleStream, eleInfo;
+
+    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(info, gEnv->getRes().c_str());
+    GetURLForComponent(mCompName, mURL, info);
+
+    eleInfo.open(info);
+    ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
+    android::Vector<FrameInfo> Info;
+    int bytesCount = 0;
+    uint32_t frameId = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    bool codecConfig = false;
+    // This test introduces empty CSD after every 20th frame
+    // and empty input frames at an interval of 5 frames.
+    while (1) {
+        if (!(frameId % 5)) {
+            if (!(frameId % 20)) flags = 32;
+            else flags = 0;
+            bytesCount = 0;
+        } else {
+            if (!(eleInfo >> bytesCount)) break;
+            eleInfo >> flags;
+            eleInfo >> timestamp;
+            codecConfig = flags ?
+                ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+        }
+        Info.push_back({bytesCount, flags, timestamp});
+        frameId++;
+    }
+    eleInfo.close();
+
+    ALOGV("mURL : %s", mURL);
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
+        mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+
+    // blocking call to ensures application to Wait till all the inputs are
+    // consumed
+    if (!mEos) {
+        ALOGV("Waiting for input consumption");
+        ASSERT_NO_FATAL_FAILURE(
+            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    }
+
+    eleStream.close();
+    if (mFramesReceived != Info.size()) {
+        ALOGE("Input buffer count and Output buffer count mismatch");
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
+              Info.size());
+        ASSERT_TRUE(false);
+    }
+
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+}
+
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
index 4f86aad..5d66ee5 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
@@ -96,6 +96,7 @@
         const StringToName kStringToName[] = {
             {"aac", aac},
             {"flac", flac},
+            {"opus", opus},
             {"amrnb", amrnb},
             {"amrwb", amrwb},
         };
@@ -135,45 +136,17 @@
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
-            // handle configuration changes in work done
-            if (!work->worklets.empty() &&
-                (work->worklets.front()->output.configUpdate.size() != 0)) {
-                ALOGV("Config Update");
-                std::vector<std::unique_ptr<C2Param>> updates =
-                    std::move(work->worklets.front()->output.configUpdate);
-                std::vector<C2Param*> configParam;
-                std::vector<std::unique_ptr<C2SettingResult>> failures;
-                for (size_t i = 0; i < updates.size(); ++i) {
-                    C2Param* param = updates[i].get();
-                    if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
-                        mCsd = true;
-                    }
-                }
-            }
-            mFramesReceived++;
-            mEos = (work->worklets.front()->output.flags &
-                    C2FrameData::FLAG_END_OF_STREAM) != 0;
-            auto frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          work->input.ordinal.frameIndex.peeku());
-            ALOGV("WorkDone: frameID received %d",
-                (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
-            work->input.buffers.clear();
-            work->worklets.clear();
-            {
-                typedef std::unique_lock<std::mutex> ULock;
-                ULock l(mQueueLock);
-                mWorkQueue.push_back(std::move(work));
-                if (!mFlushedIndices.empty()) {
-                    mFlushedIndices.erase(frameIndexIt);
-                }
-                mQueueCondition.notify_all();
+            if (!work->worklets.empty()) {
+                workDone(mComponent, work, mFlushedIndices, mQueueLock,
+                         mQueueCondition, mWorkQueue, mEos, mCsd,
+                         mFramesReceived);
             }
         }
     }
     enum standardComp {
         aac,
         flac,
+        opus,
         amrnb,
         amrwb,
         unknown_comp,
@@ -275,6 +248,8 @@
          "bbb_raw_1ch_16khz_s16le.raw"},
         {Codec2AudioEncHidlTest::standardComp::flac,
          "bbb_raw_2ch_48khz_s16le.raw"},
+        {Codec2AudioEncHidlTest::standardComp::opus,
+         "bbb_raw_2ch_48khz_s16le.raw"},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -285,11 +260,11 @@
     }
 }
 
-void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
-                   std::mutex &queueLock, std::condition_variable &queueCondition,
-                   std::list<std::unique_ptr<C2Work>> &workQueue,
-                   std::list<uint64_t> &flushedIndices,
-                   std::shared_ptr<C2BlockPool> &linearPool,
+void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::list<std::unique_ptr<C2Work>>& workQueue,
+                   std::list<uint64_t>& flushedIndices,
+                   std::shared_ptr<C2BlockPool>& linearPool,
                    std::ifstream& eleStream, uint32_t nFrames,
                    int32_t samplesPerFrame, int32_t nChannels,
                    int32_t nSampleRate, bool flushed = false,
@@ -334,6 +309,7 @@
             flushedIndices.emplace_back(frameID);
         }
         char* data = (char*)malloc(bytesCount);
+        ASSERT_NE(data, nullptr);
         eleStream.read(data, bytesCount);
         ASSERT_EQ(eleStream.gcount(), bytesCount);
         std::shared_ptr<C2LinearBlock> block;
@@ -372,29 +348,6 @@
     }
 }
 
-void waitOnInputConsumption(std::mutex& queueLock,
-                            std::condition_variable& queueCondition,
-                            std::list<std::unique_ptr<C2Work>>& workQueue,
-                            size_t bufferCount = MAX_INPUT_BUFFERS) {
-    typedef std::unique_lock<std::mutex> ULock;
-    uint32_t queueSize;
-    uint32_t maxRetry = 0;
-    {
-        ULock l(queueLock);
-        queueSize = workQueue.size();
-    }
-    while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
-        ULock l(queueLock);
-        if (queueSize != workQueue.size()) {
-            queueSize = workQueue.size();
-            maxRetry = 0;
-        } else {
-            queueCondition.wait_for(l, TIME_OUT);
-            maxRetry++;
-        }
-    }
-}
-
 TEST_F(Codec2AudioEncHidlTest, validateCompName) {
     if (mDisableTest) return;
     ALOGV("Checks if the given component is a valid audio component");
@@ -425,6 +378,11 @@
             nSampleRate = 48000;
             samplesPerFrame = 1152;
             break;
+        case opus:
+            nChannels = 2;
+            nSampleRate = 48000;
+            samplesPerFrame = 960;
+            break;
         case amrnb:
             nChannels = 1;
             nSampleRate = 8000;
@@ -458,7 +416,7 @@
         ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
         ASSERT_TRUE(false);
     }
-    if ((mCompName == flac || mCompName == aac)) {
+    if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
         if (!mCsd) {
             ALOGE("CSD buffer missing");
             ASSERT_TRUE(false);
@@ -508,46 +466,6 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2AudioEncHidlTest, EmptyBufferTest) {
-    description("Tests empty input buffer");
-    if (mDisableTest) return;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-
-    typedef std::unique_lock<std::mutex> ULock;
-    std::unique_ptr<C2Work> work;
-    {
-        ULock l(mQueueLock);
-        if (!mWorkQueue.empty()) {
-            work.swap(mWorkQueue.front());
-            mWorkQueue.pop_front();
-        } else {
-            ALOGE("mWorkQueue Empty is not expected at the start of the test");
-            ASSERT_TRUE(false);
-        }
-    }
-    ASSERT_NE(work, nullptr);
-    work->input.flags = (C2FrameData::flags_t)0;
-    work->input.ordinal.timestamp = 0;
-    work->input.ordinal.frameIndex = 0;
-    work->input.buffers.clear();
-    work->worklets.clear();
-    work->worklets.emplace_back(new C2Worklet);
-
-    std::list<std::unique_ptr<C2Work>> items;
-    items.push_back(std::move(work));
-    ASSERT_EQ(mComponent->queue(&items), C2_OK);
-    uint32_t queueSize;
-    {
-        ULock l(mQueueLock);
-        queueSize = mWorkQueue.size();
-        if (queueSize < MAX_INPUT_BUFFERS) {
-            mQueueCondition.wait_for(l, TIME_OUT);
-        }
-    }
-    ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS);
-    ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
 TEST_F(Codec2AudioEncHidlTest, FlushTest) {
     description("Test Request for flush");
     if (mDisableTest) return;
@@ -574,6 +492,11 @@
             nSampleRate = 48000;
             samplesPerFrame = 1152;
             break;
+        case opus:
+            nChannels = 2;
+            nSampleRate = 48000;
+            samplesPerFrame = 960;
+            break;
         case amrnb:
             nChannels = 1;
             nSampleRate = 8000;
diff --git a/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h b/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
index 89eb69e..4d773ce 100644
--- a/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
@@ -17,8 +17,5 @@
 #ifndef MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
 #define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
 
-#define MAX_RETRY 20
-#define TIME_OUT 200ms
-#define MAX_INPUT_BUFFERS 8
 
 #endif  // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
index fdccdbb..64a458c 100644
--- a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
@@ -14,39 +14,115 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
 #define LOG_TAG "media_c2_hidl_test_common"
 #include <stdio.h>
 
 #include "media_c2_hidl_test_common.h"
-using ::android::hardware::media::c2::V1_0::FieldSupportedValues;
 
-void dumpFSV(const FieldSupportedValues& sv) {
-    ALOGD("Dumping FSV data");
-    using namespace std;
-    if (sv.type == FieldSupportedValues::Type::EMPTY) {
-        ALOGD("FSV Value is Empty");
-    }
-    if (sv.type == FieldSupportedValues::Type::RANGE) {
-        ALOGD("Dumping FSV range");
-        cout << ".range(" << sv.range.min;
-        if (sv.range.step != 0) {
-            cout << ":" << sv.range.step;
+// Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
+void testInputBuffer(
+    const std::shared_ptr<android::Codec2Client::Component>& component,
+    std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+    uint32_t flags, bool isNullBuffer) {
+    std::unique_ptr<C2Work> work;
+    {
+        typedef std::unique_lock<std::mutex> ULock;
+        ULock l(queueLock);
+        if (!workQueue.empty()) {
+            work.swap(workQueue.front());
+            workQueue.pop_front();
+        } else {
+            ASSERT_TRUE(false) << "workQueue Empty at the start of test";
         }
-        if (sv.range.num != 1 || sv.range.denom != 1) {
-            cout << ":" << sv.range.num << "/" << sv.range.denom;
-        }
-        cout << " " << sv.range.max << ")";
     }
-    if (sv.values.size()) {
-        ALOGD("Dumping FSV value");
-        cout << (sv.type == FieldSupportedValues::Type::FLAGS ? ".flags("
-                                                              : ".list(");
-        const char* sep = "";
-        for (const auto& p : sv.values) {
-            cout << sep << p;
-            sep = ",";
-        }
-        cout << ")";
+    ASSERT_NE(work, nullptr);
+
+    work->input.flags = (C2FrameData::flags_t)flags;
+    work->input.ordinal.timestamp = 0;
+    work->input.ordinal.frameIndex = 0;
+    work->input.buffers.clear();
+    if (isNullBuffer) {
+        work->input.buffers.emplace_back(nullptr);
     }
-    cout << endl;
+    work->worklets.clear();
+    work->worklets.emplace_back(new C2Worklet);
+
+    std::list<std::unique_ptr<C2Work>> items;
+    items.push_back(std::move(work));
+    ASSERT_EQ(component->queue(&items), C2_OK);
 }
+
+// Wait for all the inputs to be consumed by the plugin.
+void waitOnInputConsumption(std::mutex& queueLock,
+                            std::condition_variable& queueCondition,
+                            std::list<std::unique_ptr<C2Work>>& workQueue,
+                            size_t bufferCount) {
+    typedef std::unique_lock<std::mutex> ULock;
+    uint32_t queueSize;
+    uint32_t maxRetry = 0;
+    {
+        ULock l(queueLock);
+        queueSize = workQueue.size();
+    }
+    while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
+        ULock l(queueLock);
+        if (queueSize != workQueue.size()) {
+            queueSize = workQueue.size();
+            maxRetry = 0;
+        } else {
+            queueCondition.wait_for(l, TIME_OUT);
+            maxRetry++;
+        }
+    }
+}
+
+// process onWorkDone received by Listener
+void workDone(
+    const std::shared_ptr<android::Codec2Client::Component>& component,
+    std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+    std::mutex& queueLock, std::condition_variable& queueCondition,
+    std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+    uint32_t& framesReceived) {
+    // handle configuration changes in work done
+    if (work->worklets.front()->output.configUpdate.size() != 0) {
+        ALOGV("Config Update");
+        std::vector<std::unique_ptr<C2Param>> updates =
+            std::move(work->worklets.front()->output.configUpdate);
+        std::vector<C2Param*> configParam;
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        for (size_t i = 0; i < updates.size(); ++i) {
+            C2Param* param = updates[i].get();
+            if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
+                csd = true;
+            } else if ((param->index() ==
+                        C2StreamSampleRateInfo::output::PARAM_TYPE) ||
+                       (param->index() ==
+                        C2StreamChannelCountInfo::output::PARAM_TYPE) ||
+                       (param->index() ==
+                        C2VideoSizeStreamInfo::output::PARAM_TYPE)) {
+                configParam.push_back(param);
+            }
+        }
+        component->config(configParam, C2_DONT_BLOCK, &failures);
+        ASSERT_EQ(failures.size(), 0u);
+    }
+    framesReceived++;
+    eos = (work->worklets.front()->output.flags &
+           C2FrameData::FLAG_END_OF_STREAM) != 0;
+    auto frameIndexIt = std::find(flushedIndices.begin(), flushedIndices.end(),
+                                  work->input.ordinal.frameIndex.peeku());
+    ALOGV("WorkDone: frameID received %d",
+          (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
+    work->input.buffers.clear();
+    work->worklets.clear();
+    {
+        typedef std::unique_lock<std::mutex> ULock;
+        ULock l(queueLock);
+        workQueue.push_back(std::move(work));
+        if (!flushedIndices.empty()) {
+            flushedIndices.erase(frameIndexIt);
+        }
+        queueCondition.notify_all();
+    }
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
index f765baa..a688530 100644
--- a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
@@ -22,6 +22,7 @@
 #include <android/hardware/media/c2/1.0/types.h>
 
 #include <C2Component.h>
+#include <C2Config.h>
 #include <getopt.h>
 #include <hidl/HidlSupport.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -38,6 +39,10 @@
 
 #include <VtsHalHidlTargetTestEnvBase.h>
 
+#define MAX_RETRY 20
+#define TIME_OUT 400ms
+#define MAX_INPUT_BUFFERS 8
+
 /*
  * Handle Callback functions onWorkDone(), onTripped(),
  * onError(), onDeath(), onFramesRendered()
@@ -176,5 +181,21 @@
 /*
  * common functions declarations
  */
-void dumpFSV(const FieldSupportedValues& sv);
+void testInputBuffer(
+    const std::shared_ptr<android::Codec2Client::Component>& component,
+    std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+    uint32_t flags, bool isNullBuffer);
+
+void waitOnInputConsumption(std::mutex& queueLock,
+                            std::condition_variable& queueCondition,
+                            std::list<std::unique_ptr<C2Work>>& workQueue,
+                            size_t bufferCount = MAX_INPUT_BUFFERS);
+
+void workDone(
+    const std::shared_ptr<android::Codec2Client::Component>& component,
+    std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+    std::mutex& queueLock, std::condition_variable& queueCondition,
+    std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+    uint32_t& framesReceived);
+
 #endif  // MEDIA_C2_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
index b7fb655..ec803d7 100644
--- a/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
@@ -38,14 +38,21 @@
    public:
     virtual void SetUp() override {
         Super::SetUp();
+        mEos = false;
         mClient = android::Codec2Client::CreateFromService(
             gEnv->getInstance().c_str());
         ASSERT_NE(mClient, nullptr);
-        mListener.reset(new CodecListener());
+        mListener.reset(new CodecListener(
+            [this](std::list<std::unique_ptr<C2Work>>& workItems) {
+                handleWorkDone(workItems);
+            }));
         ASSERT_NE(mListener, nullptr);
         mClient->createComponent(gEnv->getComponent().c_str(), mListener,
                                  &mComponent);
         ASSERT_NE(mComponent, nullptr);
+        for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
+            mWorkQueue.emplace_back(new C2Work);
+        }
     }
 
     virtual void TearDown() override {
@@ -59,6 +66,23 @@
         }
         Super::TearDown();
     }
+    // callback function to process onWorkDone received by Listener
+    void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
+        for (std::unique_ptr<C2Work>& work : workItems) {
+            if (!work->worklets.empty()) {
+                bool mCsd = false;
+                uint32_t mFramesReceived = 0;
+                std::list<uint64_t> mFlushedIndices;
+                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition,
+                         mWorkQueue, mEos, mCsd, mFramesReceived);
+            }
+        }
+    }
+
+    bool mEos;
+    std::mutex mQueueLock;
+    std::condition_variable mQueueCondition;
+    std::list<std::unique_ptr<C2Work>> mWorkQueue;
 
     std::shared_ptr<android::Codec2Client> mClient;
     std::shared_ptr<android::Codec2Client::Listener> mListener;
@@ -135,8 +159,6 @@
     ALOGV("Multiple Start Stop and Reset Test");
     c2_status_t err = C2_OK;
 
-#define MAX_RETRY 16
-
     for (size_t i = 0; i < MAX_RETRY; i++) {
         err = mComponent->start();
         ASSERT_EQ(err, C2_OK);
@@ -184,13 +206,44 @@
     ASSERT_EQ(err, C2_OK);
     ASSERT_EQ(failures.size(), 0u);
 
-#define MAX_RETRY 16
     for (size_t i = 0; i < MAX_RETRY; i++) {
         err = mComponent->release();
         ASSERT_EQ(err, C2_OK);
     }
 }
 
+class Codec2ComponentInputTests : public Codec2ComponentHidlTest,
+        public ::testing::WithParamInterface<std::pair<uint32_t, bool> > {
+};
+
+TEST_P(Codec2ComponentInputTests, InputBufferTest) {
+    description("Tests for different inputs");
+
+    uint32_t flags = GetParam().first;
+    bool isNullBuffer = GetParam().second;
+    if (isNullBuffer) ALOGD("Testing for null input buffer with flag : %u", flags);
+    else ALOGD("Testing for empty input buffer with flag : %u", flags);
+    mEos = false;
+    ASSERT_EQ(mComponent->start(), C2_OK);
+    ASSERT_NO_FATAL_FAILURE(testInputBuffer(
+        mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
+
+    ALOGD("Waiting for input consumption");
+    ASSERT_NO_FATAL_FAILURE(
+        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+
+    if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
+    ASSERT_EQ(mComponent->stop(), C2_OK);
+    ASSERT_EQ(mComponent->reset(), C2_OK);
+}
+
+INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests, ::testing::Values(
+    std::make_pair(0, true),
+    std::make_pair(C2FrameData::FLAG_END_OF_STREAM, true),
+    std::make_pair(0, false),
+    std::make_pair(C2FrameData::FLAG_CODEC_CONFIG, false),
+    std::make_pair(C2FrameData::FLAG_END_OF_STREAM, false)));
+
 }  // anonymous namespace
 
 // TODO: Add test for Invalid work,
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1 b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1
new file mode 100644
index 0000000..1d67af9
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info
new file mode 100644
index 0000000..cc51168
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info
@@ -0,0 +1,300 @@
+6027 1 0
+6879 0 33000
+5 0 66000
+532 0 100000
+5 0 133000
+2458 0 166000
+5 0 200000
+475 0 233000
+5 0 266000
+1262 0 300000
+5 0 333000
+554 0 366000
+27 0 400000
+6971 0 433000
+5 0 466000
+601 0 500000
+5 0 533000
+3276 0 566000
+5 0 600000
+658 0 633000
+5 0 666000
+1680 0 700000
+5 0 733000
+610 0 766000
+24 0 800000
+6728 0 833000
+5 0 866000
+764 0 900000
+5 0 933000
+2656 0 966000
+5 0 1000000
+462 0 1033000
+5 0 1066000
+1459 0 1100000
+5 0 1133000
+608 0 1166000
+24 0 1200000
+7038 0 1233000
+5 0 1266000
+721 0 1300000
+5 0 1333000
+3102 0 1366000
+5 0 1400000
+752 0 1433000
+5 0 1466000
+1815 0 1500000
+5 0 1533000
+755 0 1566000
+25 0 1600000
+7657 0 1633000
+5 0 1666000
+852 0 1700000
+5 0 1733000
+3537 0 1766000
+5 0 1800000
+673 0 1833000
+5 0 1866000
+1774 0 1900000
+5 0 1933000
+554 0 1966000
+24 0 2000000
+8028 0 2033000
+5 0 2066000
+715 0 2100000
+5 0 2133000
+3395 0 2166000
+5 0 2200000
+736 0 2233000
+5 0 2266000
+1759 0 2300000
+5 0 2333000
+605 0 2366000
+23 0 2400000
+7651 0 2433000
+5 0 2466000
+619 0 2500000
+5 0 2533000
+2788 0 2566000
+5 0 2600000
+556 0 2633000
+5 0 2666000
+1335 0 2700000
+5 0 2733000
+521 0 2766000
+24 0 2800000
+2274 0 2833000
+676 0 2866000
+25 0 2900000
+6224 0 2933000
+5798 0 2966000
+5 0 3000000
+448 0 3033000
+5 0 3066000
+1950 0 3100000
+5 0 3133000
+386 0 3166000
+5 0 3200000
+1218 0 3233000
+5 0 3266000
+1316 0 3300000
+5 0 3333000
+580 0 3366000
+26 0 3400000
+6673 0 3433000
+5 0 3466000
+473 0 3500000
+5 0 3533000
+2467 0 3566000
+5 0 3600000
+429 0 3633000
+5 0 3666000
+1420 0 3700000
+5 0 3733000
+583 0 3766000
+29 0 3800000
+8492 0 3833000
+5 0 3866000
+720 0 3900000
+5 0 3933000
+3635 0 3966000
+5 0 4000000
+621 0 4033000
+5 0 4066000
+1969 0 4100000
+5 0 4133000
+49 0 4166000
+25 0 4200000
+7416 0 4233000
+5 0 4266000
+947 0 4300000
+5 0 4333000
+3713 0 4366000
+5 0 4400000
+714 0 4433000
+5 0 4466000
+2003 0 4500000
+5 0 4533000
+750 0 4566000
+25 0 4600000
+8470 0 4633000
+5 0 4666000
+737 0 4700000
+5 0 4733000
+4094 0 4766000
+5 0 4800000
+1019 0 4833000
+5 0 4866000
+2160 0 4900000
+5 0 4933000
+828 0 4966000
+24 0 5000000
+9282 0 5033000
+5 0 5066000
+655 0 5100000
+5 0 5133000
+3491 0 5166000
+5 0 5200000
+651 0 5233000
+5 0 5266000
+1906 0 5300000
+5 0 5333000
+662 0 5366000
+24 0 5400000
+9724 0 5433000
+5 0 5466000
+617 0 5500000
+5 0 5533000
+3145 0 5566000
+5 0 5600000
+578 0 5633000
+5 0 5666000
+1592 0 5700000
+5 0 5733000
+569 0 5766000
+25 0 5800000
+10015 0 5833000
+5 0 5866000
+609 0 5900000
+5 0 5933000
+3618 0 5966000
+5 0 6000000
+734 0 6033000
+5 0 6066000
+1748 0 6100000
+5 0 6133000
+550 0 6166000
+24 0 6200000
+8806 0 6233000
+5 0 6266000
+498 0 6300000
+5 0 6333000
+2913 0 6366000
+5 0 6400000
+597 0 6433000
+5 0 6466000
+1235 0 6500000
+5 0 6533000
+362 0 6566000
+24 0 6600000
+6592 0 6633000
+5 0 6666000
+468 0 6700000
+5 0 6733000
+1920 0 6766000
+5 0 6800000
+419 0 6833000
+5 0 6866000
+843 0 6900000
+5 0 6933000
+237 0 6966000
+24 0 7000000
+2687 0 7033000
+5 0 7066000
+399 0 7100000
+5 0 7133000
+200 0 7166000
+143 0 7200000
+25 0 7233000
+12603 0 7266000
+1139 0 7300000
+5 0 7333000
+56 0 7366000
+5 0 7400000
+273 0 7433000
+5 0 7466000
+48 0 7500000
+5 0 7533000
+102 0 7566000
+5 0 7600000
+39 0 7633000
+24 0 7666000
+3635 0 7700000
+5 0 7733000
+46 0 7766000
+5 0 7800000
+647 0 7833000
+5 0 7866000
+61 0 7900000
+5 0 7933000
+824 0 7966000
+5 0 8000000
+691 0 8033000
+27 0 8066000
+4573 0 8100000
+5 0 8133000
+473 0 8166000
+5 0 8200000
+1637 0 8233000
+5 0 8266000
+451 0 8300000
+5 0 8333000
+969 0 8366000
+5 0 8400000
+234 0 8433000
+24 0 8466000
+3361 0 8500000
+5 0 8533000
+168 0 8566000
+5 0 8600000
+662 0 8633000
+5 0 8666000
+129 0 8700000
+5 0 8733000
+443 0 8766000
+5 0 8800000
+183 0 8833000
+23 0 8866000
+2769 0 8900000
+5 0 8933000
+182 0 8966000
+5 0 9000000
+890 0 9033000
+5 0 9066000
+171 0 9100000
+5 0 9133000
+599 0 9166000
+5 0 9200000
+236 0 9233000
+23 0 9266000
+2316 0 9300000
+5 0 9333000
+333 0 9366000
+5 0 9400000
+759 0 9433000
+5 0 9466000
+210 0 9500000
+5 0 9533000
+324 0 9566000
+5 0 9600000
+98 0 9633000
+23 0 9666000
+1107 0 9700000
+5 0 9733000
+42 0 9766000
+5 0 9800000
+145 0 9833000
+5 0 9866000
+109 0 9900000
+89 0 9933000
+24 0 9966000
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1 b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1
new file mode 100644
index 0000000..529bace
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info
new file mode 100644
index 0000000..fca7833
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info
@@ -0,0 +1,167 @@
+12571 1 0
+9881 0 33000
+5 0 66000
+544 0 100000
+5 0 133000
+2642 0 166000
+5 0 200000
+531 0 233000
+5 0 266000
+1359 0 300000
+5 0 333000
+551 0 366000
+28 0 400000
+10791 0 433000
+5 0 466000
+655 0 500000
+5 0 533000
+3769 0 566000
+5 0 600000
+711 0 633000
+5 0 666000
+2004 0 700000
+5 0 733000
+657 0 766000
+26 0 800000
+8969 0 833000
+5 0 866000
+630 0 900000
+5 0 933000
+2787 0 966000
+5 0 1000000
+404 0 1033000
+5 0 1066000
+1518 0 1100000
+5 0 1133000
+493 0 1166000
+26 0 1200000
+9900 0 1233000
+5 0 1266000
+620 0 1300000
+5 0 1333000
+3072 0 1366000
+5 0 1400000
+668 0 1433000
+5 0 1466000
+1821 0 1500000
+5 0 1533000
+682 0 1566000
+26 0 1600000
+9560 0 1633000
+5 0 1666000
+667 0 1700000
+5 0 1733000
+3249 0 1766000
+5 0 1800000
+589 0 1833000
+5 0 1866000
+1816 0 1900000
+5 0 1933000
+548 0 1966000
+26 0 2000000
+9916 0 2033000
+5 0 2066000
+628 0 2100000
+5 0 2133000
+3034 0 2166000
+5 0 2200000
+590 0 2233000
+5 0 2266000
+1581 0 2300000
+5 0 2333000
+524 0 2366000
+26 0 2400000
+8182 0 2433000
+5 0 2466000
+552 0 2500000
+5 0 2533000
+2412 0 2566000
+5 0 2600000
+489 0 2633000
+5 0 2666000
+1227 0 2700000
+5 0 2733000
+432 0 2766000
+26 0 2800000
+2017 0 2833000
+516 0 2866000
+26 0 2900000
+16619 0 2933000
+6710 0 2966000
+5 0 3000000
+425 0 3033000
+5 0 3066000
+1964 0 3100000
+5 0 3133000
+386 0 3166000
+5 0 3200000
+1129 0 3233000
+5 0 3266000
+1156 0 3300000
+5 0 3333000
+486 0 3366000
+28 0 3400000
+10304 0 3433000
+5 0 3466000
+412 0 3500000
+5 0 3533000
+2608 0 3566000
+5 0 3600000
+397 0 3633000
+5 0 3666000
+1514 0 3700000
+5 0 3733000
+533 0 3766000
+26 0 3800000
+11698 0 3833000
+5 0 3866000
+542 0 3900000
+5 0 3933000
+3334 0 3966000
+5 0 4000000
+547 0 4033000
+5 0 4066000
+1809 0 4100000
+5 0 4133000
+55 0 4166000
+26 0 4200000
+9496 0 4233000
+5 0 4266000
+658 0 4300000
+5 0 4333000
+3232 0 4366000
+5 0 4400000
+600 0 4433000
+5 0 4466000
+1766 0 4500000
+5 0 4533000
+550 0 4566000
+25 0 4600000
+9951 0 4633000
+5 0 4666000
+624 0 4700000
+5 0 4733000
+3617 0 4766000
+5 0 4800000
+644 0 4833000
+5 0 4866000
+1841 0 4900000
+5 0 4933000
+649 0 4966000
+25 0 5000000
+9901 0 5033000
+5 0 5066000
+515 0 5100000
+5 0 5133000
+2814 0 5166000
+5 0 5200000
+511 0 5233000
+5 0 5266000
+1521 0 5300000
+5 0 5333000
+509 0 5366000
+26 0 5400000
+10579 0 5433000
+5 0 5466000
+575 0 5500000
+5 0 5533000
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
index 8420cab..9a42d72 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
@@ -101,7 +101,7 @@
 
         const StringToName kStringToName[] = {
             {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
-            {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
+            {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
         };
 
         const size_t kNumStringToName =
@@ -142,79 +142,48 @@
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
-            // handle configuration changes in work done
-            if (!work->worklets.empty() &&
-                (work->worklets.front()->output.configUpdate.size() != 0)) {
-                ALOGV("Config Update");
-                std::vector<std::unique_ptr<C2Param>> updates =
-                    std::move(work->worklets.front()->output.configUpdate);
-                std::vector<C2Param*> configParam;
-                std::vector<std::unique_ptr<C2SettingResult>> failures;
-                for (size_t i = 0; i < updates.size(); ++i) {
-                    C2Param* param = updates[i].get();
-                    if (param->index() ==
-                        C2VideoSizeStreamInfo::output::PARAM_TYPE) {
-                        ALOGV("Received C2VideoSizeStreamInfo");
-                        configParam.push_back(param);
-                    }
-                }
-                mComponent->config(configParam, C2_DONT_BLOCK, &failures);
-                ASSERT_EQ(failures.size(), 0u);
-            }
+            if (!work->worklets.empty()) {
+                // For decoder components current timestamp always exceeds
+                // previous timestamp
+                typedef std::unique_lock<std::mutex> ULock;
+                bool codecConfig = ((work->worklets.front()->output.flags &
+                                     C2FrameData::FLAG_CODEC_CONFIG) != 0);
+                if (!codecConfig &&
+                    !work->worklets.front()->output.buffers.empty()) {
+                    EXPECT_GE(
+                        (work->worklets.front()->output.ordinal.timestamp.peeku()),
+                        mTimestampUs);
+                    mTimestampUs =
+                        work->worklets.front()->output.ordinal.timestamp.peeku();
 
-            mFramesReceived++;
-            mEos = (work->worklets.front()->output.flags &
-                    C2FrameData::FLAG_END_OF_STREAM) != 0;
-            auto frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          work->input.ordinal.frameIndex.peeku());
-
-            // For decoder components current timestamp always exceeds
-            // previous timestamp
-            typedef std::unique_lock<std::mutex> ULock;
-            bool codecConfig = ((work->worklets.front()->output.flags &
-                                 C2FrameData::FLAG_CODEC_CONFIG) != 0);
-            if (!codecConfig &&
-                !work->worklets.front()->output.buffers.empty()) {
-                EXPECT_GE(
-                    (work->worklets.front()->output.ordinal.timestamp.peeku()),
-                    mTimestampUs);
-                mTimestampUs =
-                    work->worklets.front()->output.ordinal.timestamp.peeku();
-
-                ULock l(mQueueLock);
-                if (mTimestampDevTest) {
-                    bool tsHit = false;
-                    std::list<uint64_t>::iterator it = mTimestampUslist.begin();
-                    while (it != mTimestampUslist.end()) {
-                        if (*it == mTimestampUs) {
-                            mTimestampUslist.erase(it);
-                            tsHit = true;
-                            break;
+                    ULock l(mQueueLock);
+                    if (mTimestampDevTest) {
+                        bool tsHit = false;
+                        std::list<uint64_t>::iterator it = mTimestampUslist.begin();
+                        while (it != mTimestampUslist.end()) {
+                            if (*it == mTimestampUs) {
+                                mTimestampUslist.erase(it);
+                                tsHit = true;
+                                break;
+                            }
+                            it++;
                         }
-                        it++;
-                    }
-                    if (tsHit == false) {
-                        if (mTimestampUslist.empty() == false) {
-                            EXPECT_EQ(tsHit, true)
-                                << "TimeStamp not recognized";
-                        } else {
-                            std::cout << "[   INFO   ] Received non-zero "
-                                         "output / TimeStamp not recognized \n";
+                        if (tsHit == false) {
+                            if (mTimestampUslist.empty() == false) {
+                                EXPECT_EQ(tsHit, true)
+                                    << "TimeStamp not recognized";
+                            } else {
+                                std::cout << "[   INFO   ] Received non-zero "
+                                             "output / TimeStamp not recognized \n";
+                            }
                         }
                     }
                 }
-            }
-
-            work->input.buffers.clear();
-            work->worklets.clear();
-            {
-                ULock l(mQueueLock);
-                mWorkQueue.push_back(std::move(work));
-                if (!mFlushedIndices.empty()) {
-                    mFlushedIndices.erase(frameIndexIt);
-                }
-                mQueueCondition.notify_all();
+                bool mCsd;
+                workDone(mComponent, work, mFlushedIndices, mQueueLock,
+                         mQueueCondition, mWorkQueue, mEos, mCsd,
+                         mFramesReceived);
+                (void)mCsd;
             }
         }
     }
@@ -227,6 +196,7 @@
         hevc,
         vp8,
         vp9,
+        av1,
         unknown_comp,
     };
 
@@ -341,6 +311,11 @@
           "bbb_vp9_640x360_1600kbps_30fps.vp9"},
          {"bbb_vp9_176x144_285kbps_60fps.info",
           "bbb_vp9_640x360_1600kbps_30fps.info"}},
+        {Codec2VideoDecHidlTest::standardComp::av1,
+         {"bbb_av1_640_360.av1",
+          "bbb_av1_176_144.av1"},
+         {"bbb_av1_640_360.info",
+          "bbb_av1_176_144.info"}},
     };
 
     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -352,11 +327,11 @@
     }
 }
 
-void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
-                   std::mutex &queueLock, std::condition_variable &queueCondition,
-                   std::list<std::unique_ptr<C2Work>> &workQueue,
-                   std::list<uint64_t> &flushedIndices,
-                   std::shared_ptr<C2BlockPool> &linearPool,
+void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::list<std::unique_ptr<C2Work>>& workQueue,
+                   std::list<uint64_t>& flushedIndices,
+                   std::shared_ptr<C2BlockPool>& linearPool,
                    std::ifstream& eleStream,
                    android::Vector<FrameInfo>* Info,
                    int offset, int range, bool signalEOS = true) {
@@ -397,35 +372,37 @@
 
         int size = (*Info)[frameID].bytesCount;
         char* data = (char*)malloc(size);
+        ASSERT_NE(data, nullptr);
 
         eleStream.read(data, size);
         ASSERT_EQ(eleStream.gcount(), size);
 
-        std::shared_ptr<C2LinearBlock> block;
-        ASSERT_EQ(C2_OK,
-                  linearPool->fetchLinearBlock(
-                      size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
-                      &block));
-        ASSERT_TRUE(block);
-
-        // Write View
-        C2WriteView view = block->map().get();
-        if (view.error() != C2_OK) {
-            fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
-            break;
-        }
-        ASSERT_EQ((size_t)size, view.capacity());
-        ASSERT_EQ(0u, view.offset());
-        ASSERT_EQ((size_t)size, view.size());
-
-        memcpy(view.base(), data, size);
-
         work->input.buffers.clear();
-        work->input.buffers.emplace_back(new LinearBuffer(block));
+        if (size) {
+            std::shared_ptr<C2LinearBlock> block;
+            ASSERT_EQ(C2_OK,
+                    linearPool->fetchLinearBlock(
+                        size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+                        &block));
+            ASSERT_TRUE(block);
+
+            // Write View
+            C2WriteView view = block->map().get();
+            if (view.error() != C2_OK) {
+                fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
+                break;
+            }
+            ASSERT_EQ((size_t)size, view.capacity());
+            ASSERT_EQ(0u, view.offset());
+            ASSERT_EQ((size_t)size, view.size());
+
+            memcpy(view.base(), data, size);
+
+            work->input.buffers.emplace_back(new LinearBuffer(block));
+            free(data);
+        }
         work->worklets.clear();
         work->worklets.emplace_back(new C2Worklet);
-        free(data);
-
         std::list<std::unique_ptr<C2Work>> items;
         items.push_back(std::move(work));
 
@@ -437,29 +414,6 @@
     }
 }
 
-void waitOnInputConsumption(std::mutex& queueLock,
-                            std::condition_variable& queueCondition,
-                            std::list<std::unique_ptr<C2Work>>& workQueue,
-                            size_t bufferCount = MAX_INPUT_BUFFERS) {
-    typedef std::unique_lock<std::mutex> ULock;
-    uint32_t queueSize;
-    uint32_t maxRetry = 0;
-    {
-        ULock l(queueLock);
-        queueSize = workQueue.size();
-    }
-    while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
-        ULock l(queueLock);
-        if (queueSize != workQueue.size()) {
-            queueSize = workQueue.size();
-            maxRetry = 0;
-        } else {
-            queueCondition.wait_for(l, TIME_OUT);
-            maxRetry++;
-        }
-    }
-}
-
 TEST_F(Codec2VideoDecHidlTest, validateCompName) {
     if (mDisableTest) return;
     ALOGV("Checks if the given component is a valid video component");
@@ -678,8 +632,8 @@
         EXPECT_GE(mFramesReceived, 1U);
         ASSERT_EQ(mEos, true);
         ASSERT_EQ(mComponent->stop(), C2_OK);
-        ASSERT_EQ(mComponent->release(), C2_OK);
     }
+    ASSERT_EQ(mComponent->release(), C2_OK);
 }
 
 TEST_F(Codec2VideoDecHidlTest, EOSTest) {
@@ -712,7 +666,6 @@
     ASSERT_EQ(mComponent->queue(&items), C2_OK);
 
     {
-        typedef std::unique_lock<std::mutex> ULock;
         ULock l(mQueueLock);
         if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
             mQueueCondition.wait_for(l, TIME_OUT);
@@ -723,46 +676,6 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2VideoDecHidlTest, EmptyBufferTest) {
-    description("Tests empty input buffer");
-    if (mDisableTest) return;
-    typedef std::unique_lock<std::mutex> ULock;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-    std::unique_ptr<C2Work> work;
-    // Prepare C2Work
-    {
-        ULock l(mQueueLock);
-        if (!mWorkQueue.empty()) {
-            work.swap(mWorkQueue.front());
-            mWorkQueue.pop_front();
-        } else {
-            ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test";
-        }
-    }
-    ASSERT_NE(work, nullptr);
-
-    work->input.flags = (C2FrameData::flags_t)0;
-    work->input.ordinal.timestamp = 0;
-    work->input.ordinal.frameIndex = 0;
-    work->input.buffers.clear();
-    work->worklets.clear();
-    work->worklets.emplace_back(new C2Worklet);
-
-    std::list<std::unique_ptr<C2Work>> items;
-    items.push_back(std::move(work));
-    ASSERT_EQ(mComponent->queue(&items), C2_OK);
-
-    {
-        typedef std::unique_lock<std::mutex> ULock;
-        ULock l(mQueueLock);
-        if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
-            mQueueCondition.wait_for(l, TIME_OUT);
-        }
-    }
-    ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
-    ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
 TEST_F(Codec2VideoDecHidlTest, FlushTest) {
     description("Tests Flush calls");
     if (mDisableTest) return;
@@ -874,6 +787,69 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
+TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
+    description("Decode with multiple empty input frames");
+    if (mDisableTest) return;
+
+    char mURL[512], info[512];
+    std::ifstream eleStream, eleInfo;
+
+    strcpy(mURL, gEnv->getRes().c_str());
+    strcpy(info, gEnv->getRes().c_str());
+    GetURLForComponent(mCompName, mURL, info);
+
+    eleInfo.open(info);
+    ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
+    android::Vector<FrameInfo> Info;
+    int bytesCount = 0;
+    uint32_t frameId = 0;
+    uint32_t flags = 0;
+    uint32_t timestamp = 0;
+    bool codecConfig = false;
+    // This test introduces empty CSD after every 20th frame
+    // and empty input frames at an interval of 5 frames.
+    while (1) {
+        if (!(frameId % 5)) {
+            if (!(frameId % 20)) flags = 32;
+            else flags = 0;
+            bytesCount = 0;
+        } else {
+            if (!(eleInfo >> bytesCount)) break;
+            eleInfo >> flags;
+            eleInfo >> timestamp;
+            codecConfig = flags ?
+                ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+        }
+        Info.push_back({bytesCount, flags, timestamp});
+        frameId++;
+    }
+    eleInfo.close();
+
+    ASSERT_EQ(mComponent->start(), C2_OK);
+    ALOGV("mURL : %s", mURL);
+    eleStream.open(mURL, std::ifstream::binary);
+    ASSERT_EQ(eleStream.is_open(), true);
+    ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+        mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
+        mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+
+    // blocking call to ensures application to Wait till all the inputs are
+    // consumed
+    if (!mEos) {
+        ALOGV("Waiting for input consumption");
+        ASSERT_NO_FATAL_FAILURE(
+            waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+    }
+
+    eleStream.close();
+    if (mFramesReceived != Info.size()) {
+        ALOGE("Input buffer count and Output buffer count mismatch");
+        ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
+              Info.size());
+        ASSERT_TRUE(false);
+    }
+}
+
 }  // anonymous namespace
 
 // TODO : Video specific configuration Test
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
index 87b7902..8585c87 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
@@ -139,40 +139,11 @@
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
         for (std::unique_ptr<C2Work>& work : workItems) {
-            // handle configuration changes in work done
-            if (!work->worklets.empty() &&
-                (work->worklets.front()->output.configUpdate.size() != 0)) {
-                ALOGV("Config Update");
-                std::vector<std::unique_ptr<C2Param>> updates =
-                    std::move(work->worklets.front()->output.configUpdate);
-                std::vector<C2Param*> configParam;
-                std::vector<std::unique_ptr<C2SettingResult>> failures;
-                for (size_t i = 0; i < updates.size(); ++i) {
-                    C2Param* param = updates[i].get();
-                    if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
-                        mCsd = true;
-                    }
-                }
-            }
-            mFramesReceived++;
-            if (work->result != C2_OK) mFailedWorkReceived++;
-            mEos = (work->worklets.front()->output.flags &
-                    C2FrameData::FLAG_END_OF_STREAM) != 0;
-            auto frameIndexIt =
-                std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
-                          work->input.ordinal.frameIndex.peeku());
-            ALOGV("WorkDone: frameID received %d",
-                (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
-            work->input.buffers.clear();
-            work->worklets.clear();
-            {
-                typedef std::unique_lock<std::mutex> ULock;
-                ULock l(mQueueLock);
-                mWorkQueue.push_back(std::move(work));
-                if (!mFlushedIndices.empty()) {
-                    mFlushedIndices.erase(frameIndexIt);
-                }
-                mQueueCondition.notify_all();
+            if (!work->worklets.empty()) {
+                if (work->result != C2_OK) mFailedWorkReceived++;
+                workDone(mComponent, work, mFlushedIndices, mQueueLock,
+                         mQueueCondition, mWorkQueue, mEos, mCsd,
+                         mFramesReceived);
             }
         }
     }
@@ -272,11 +243,11 @@
     strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
 }
 
-void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
-                   std::mutex &queueLock, std::condition_variable &queueCondition,
-                   std::list<std::unique_ptr<C2Work>> &workQueue,
-                   std::list<uint64_t> &flushedIndices,
-                   std::shared_ptr<C2BlockPool> &graphicPool,
+void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+                   std::mutex &queueLock, std::condition_variable& queueCondition,
+                   std::list<std::unique_ptr<C2Work>>& workQueue,
+                   std::list<uint64_t>& flushedIndices,
+                   std::shared_ptr<C2BlockPool>& graphicPool,
                    std::ifstream& eleStream, uint32_t frameID,
                    uint32_t nFrames, uint32_t nWidth, int32_t nHeight,
                    bool flushed = false,bool signalEOS = true) {
@@ -319,6 +290,7 @@
             flushedIndices.emplace_back(frameID);
         }
         char* data = (char*)malloc(bytesCount);
+        ASSERT_NE(data, nullptr);
         memset(data, 0, bytesCount);
         if (eleStream.is_open()) {
             eleStream.read(data, bytesCount);
@@ -365,30 +337,6 @@
     }
 }
 
-void waitOnInputConsumption(std::mutex &queueLock,
-                            std::condition_variable &queueCondition,
-                            std::list<std::unique_ptr<C2Work>> &workQueue,
-                            size_t bufferCount = MAX_INPUT_BUFFERS) {
-    typedef std::unique_lock<std::mutex> ULock;
-    uint32_t queueSize;
-    int maxRetry = 0;
-    {
-        ULock l(queueLock);
-        queueSize = workQueue.size();
-    }
-    while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
-        ULock l(queueLock);
-        if (queueSize != workQueue.size()) {
-            queueSize = workQueue.size();
-            maxRetry = 0;
-        } else {
-            queueCondition.wait_for(l, TIME_OUT);
-            maxRetry++;
-        }
-    }
-}
-
-
 TEST_F(Codec2VideoEncHidlTest, validateCompName) {
     if (mDisableTest) return;
     ALOGV("Checks if the given component is a valid video component");
@@ -488,46 +436,6 @@
     ASSERT_EQ(mComponent->stop(), C2_OK);
 }
 
-TEST_F(Codec2VideoEncHidlTest, EmptyBufferTest) {
-    description("Tests empty input buffer");
-    if (mDisableTest) return;
-    ASSERT_EQ(mComponent->start(), C2_OK);
-
-    typedef std::unique_lock<std::mutex> ULock;
-    std::unique_ptr<C2Work> work;
-    {
-        ULock l(mQueueLock);
-        if (!mWorkQueue.empty()) {
-            work.swap(mWorkQueue.front());
-            mWorkQueue.pop_front();
-        } else {
-            ALOGE("mWorkQueue Empty is not expected at the start of the test");
-            ASSERT_TRUE(false);
-        }
-    }
-    ASSERT_NE(work, nullptr);
-    work->input.flags = (C2FrameData::flags_t)0;
-    work->input.ordinal.timestamp = 0;
-    work->input.ordinal.frameIndex = 0;
-    work->input.buffers.clear();
-    work->worklets.clear();
-    work->worklets.emplace_back(new C2Worklet);
-
-    std::list<std::unique_ptr<C2Work>> items;
-    items.push_back(std::move(work));
-    ASSERT_EQ(mComponent->queue(&items), C2_OK);
-    uint32_t queueSize;
-    {
-        ULock l(mQueueLock);
-        queueSize = mWorkQueue.size();
-        if (queueSize < MAX_INPUT_BUFFERS) {
-            mQueueCondition.wait_for(l, TIME_OUT);
-        }
-    }
-    ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS);
-    ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
 TEST_F(Codec2VideoEncHidlTest, FlushTest) {
     description("Test Request for flush");
     if (mDisableTest) return;
diff --git a/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h b/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
index 1215b13..dd45557 100644
--- a/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
@@ -17,9 +17,6 @@
 #ifndef MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
 #define MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
 
-#define MAX_RETRY 20
-#define TIME_OUT 400ms
-#define MAX_INPUT_BUFFERS 8
 #define ENCODER_TIMESTAMP_INCREMENT 40000
 #define ENC_NUM_FRAMES 32
 #define ENC_DEFAULT_FRAME_WIDTH 352
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 8d028e1..1744d3d 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -11,7 +11,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 1fdac05..4a30740 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -29,10 +29,8 @@
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/foundation/ColorUtils.h>
 #include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaBufferBase.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
 #include <media/stagefright/MetaDataUtils.h>
 #include <utils/String8.h>
 
@@ -127,7 +125,7 @@
     BlockIterator &operator=(const BlockIterator &);
 };
 
-struct MatroskaSource : public MediaTrackHelperV2 {
+struct MatroskaSource : public MediaTrackHelperV3 {
     MatroskaSource(MatroskaExtractor *extractor, size_t index);
 
     virtual media_status_t start();
@@ -136,7 +134,7 @@
     virtual media_status_t getFormat(AMediaFormat *);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options);
 
 protected:
     virtual ~MatroskaSource();
@@ -156,11 +154,11 @@
     BlockIterator mBlockIter;
     ssize_t mNALSizeLen;  // for type AVC or HEVC
 
-    List<MediaBufferBase *> mPendingFrames;
+    List<MediaBufferHelperV3 *> mPendingFrames;
 
     status_t advance();
 
-    status_t setWebmBlockCryptoInfo(MediaBufferBase *mbuf);
+    status_t setWebmBlockCryptoInfo(MediaBufferHelperV3 *mbuf);
     media_status_t readBlock();
     void clearPendingFrames();
 
@@ -265,6 +263,8 @@
         return AMEDIA_ERROR_MALFORMED;
     }
 
+    // allocate one small initial buffer, but leave plenty of room to grow
+    mBufferGroup->init(1 /* number of buffers */, 1024 /* buffer size */, 64 /* growth limit */);
     mBlockIter.reset();
 
     return AMEDIA_OK;
@@ -569,7 +569,7 @@
 
 void MatroskaSource::clearPendingFrames() {
     while (!mPendingFrames.empty()) {
-        MediaBufferBase *frame = *mPendingFrames.begin();
+        MediaBufferHelperV3 *frame = *mPendingFrames.begin();
         mPendingFrames.erase(mPendingFrames.begin());
 
         frame->release();
@@ -577,7 +577,7 @@
     }
 }
 
-status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferBase *mbuf) {
+status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferHelperV3 *mbuf) {
     if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
         // 1-byte signal
         return ERROR_MALFORMED;
@@ -591,7 +591,7 @@
         return ERROR_MALFORMED;
     }
 
-    MetaDataBase &meta = mbuf->meta_data();
+    AMediaFormat *meta = mbuf->meta_data();
     if (encrypted) {
         uint8_t ctrCounter[16] = { 0 };
         const uint8_t *keyId;
@@ -599,9 +599,9 @@
         AMediaFormat *trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
         AMediaFormat_getBuffer(trackMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY,
                 (void**)&keyId, &keyIdSize);
-        meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
+        AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_KEY, keyId, keyIdSize);
         memcpy(ctrCounter, data + 1, 8);
-        meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
+        AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_IV, ctrCounter, 16);
         if (partitioned) {
             /*  0                   1                   2                   3
              *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -654,8 +654,10 @@
             }
             uint32_t sizeofPlainSizes = sizeof(uint32_t) * plainSizes.size();
             uint32_t sizeofEncryptedSizes = sizeof(uint32_t) * encryptedSizes.size();
-            meta.setData(kKeyPlainSizes, 0, plainSizes.data(), sizeofPlainSizes);
-            meta.setData(kKeyEncryptedSizes, 0, encryptedSizes.data(), sizeofEncryptedSizes);
+            AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+                    plainSizes.data(), sizeofPlainSizes);
+            AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+                    encryptedSizes.data(), sizeofEncryptedSizes);
             mbuf->set_range(frameOffset, mbuf->range_length() - frameOffset);
         } else {
             /*
@@ -675,8 +677,10 @@
              */
             int32_t plainSizes[] = { 0 };
             int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
-            meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
-            meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+            AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+                    plainSizes, sizeof(plainSizes));
+            AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+                    encryptedSizes, sizeof(encryptedSizes));
             mbuf->set_range(9, mbuf->range_length() - 9);
         }
     } else {
@@ -693,8 +697,10 @@
          */
         int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
         int32_t encryptedSizes[] = { 0 };
-        meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
-        meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+        AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+                plainSizes, sizeof(plainSizes));
+        AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+                encryptedSizes, sizeof(encryptedSizes));
         mbuf->set_range(1, mbuf->range_length() - 1);
     }
 
@@ -721,14 +727,17 @@
         }
 
         len += trackInfo->mHeaderLen;
-        MediaBufferBase *mbuf = MediaBufferBase::Create(len);
+        MediaBufferHelperV3 *mbuf;
+        mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */, len /* requested size */);
+        mbuf->set_range(0, len);
         uint8_t *data = static_cast<uint8_t *>(mbuf->data());
         if (trackInfo->mHeader) {
             memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
         }
 
-        mbuf->meta_data().setInt64(kKeyTime, timeUs);
-        mbuf->meta_data().setInt32(kKeyIsSyncFrame, block->IsKey());
+        AMediaFormat *meta = mbuf->meta_data();
+        AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+        AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, block->IsKey());
 
         status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
         if (err == OK
@@ -754,7 +763,7 @@
 }
 
 media_status_t MatroskaSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t targetSampleTimeUs = -1ll;
@@ -790,13 +799,13 @@
         }
     }
 
-    MediaBufferBase *frame = *mPendingFrames.begin();
+    MediaBufferHelperV3 *frame = *mPendingFrames.begin();
     mPendingFrames.erase(mPendingFrames.begin());
 
     if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
         if (targetSampleTimeUs >= 0ll) {
-            frame->meta_data().setInt64(
-                    kKeyTargetTime, targetSampleTimeUs);
+            AMediaFormat_setInt64(frame->meta_data(),
+                    AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
         }
 
         *out = frame;
@@ -819,7 +828,7 @@
     size_t srcSize = frame->range_length();
 
     size_t dstSize = 0;
-    MediaBufferBase *buffer = NULL;
+    MediaBufferHelperV3 *buffer = NULL;
     uint8_t *dstPtr = NULL;
 
     for (int32_t pass = 0; pass < 2; ++pass) {
@@ -879,16 +888,20 @@
                 // each 4-byte nal size with a 4-byte start code
                 buffer = frame;
             } else {
-                buffer = MediaBufferBase::Create(dstSize);
+                mBufferGroup->acquire_buffer(
+                        &buffer, false /* nonblocking */, dstSize /* requested size */);
+                buffer->set_range(0, dstSize);
             }
 
+            AMediaFormat *frameMeta = frame->meta_data();
             int64_t timeUs;
-            CHECK(frame->meta_data().findInt64(kKeyTime, &timeUs));
+            CHECK(AMediaFormat_getInt64(frameMeta, AMEDIAFORMAT_KEY_TIME_US, &timeUs));
             int32_t isSync;
-            CHECK(frame->meta_data().findInt32(kKeyIsSyncFrame, &isSync));
+            CHECK(AMediaFormat_getInt32(frameMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, &isSync));
 
-            buffer->meta_data().setInt64(kKeyTime, timeUs);
-            buffer->meta_data().setInt32(kKeyIsSyncFrame, isSync);
+            AMediaFormat *bufMeta = buffer->meta_data();
+            AMediaFormat_setInt64(bufMeta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+            AMediaFormat_setInt32(bufMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, isSync);
 
             dstPtr = (uint8_t *)buffer->data();
         }
@@ -900,8 +913,8 @@
     }
 
     if (targetSampleTimeUs >= 0ll) {
-        buffer->meta_data().setInt64(
-                kKeyTargetTime, targetSampleTimeUs);
+        AMediaFormat_setInt64(buffer->meta_data(),
+                AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
     }
 
     *out = buffer;
@@ -992,7 +1005,7 @@
     return mTracks.size();
 }
 
-MediaTrackHelperV2 *MatroskaExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MatroskaExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
@@ -1660,22 +1673,22 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
         1,
         "Matroska Extractor",
         {
-            .v2 = [](
+            .v3 = [](
                     CDataSource *source,
                     float *confidence,
                     void **,
-                    FreeMetaFunc *) -> CreatorFuncV2 {
+                    FreeMetaFunc *) -> CreatorFuncV3 {
                 DataSourceHelper helper(source);
                 if (SniffMatroska(&helper, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractorV2* {
-                        return wrapV2(new MatroskaExtractor(new DataSourceHelper(source)));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new MatroskaExtractor(new DataSourceHelper(source)));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 2fa8881..a09256a 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -35,12 +35,12 @@
 struct DataSourceBaseReader;
 struct MatroskaSource;
 
-struct MatroskaExtractor : public MediaExtractorPluginHelperV2 {
+struct MatroskaExtractor : public MediaExtractorPluginHelperV3 {
     explicit MatroskaExtractor(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);
 
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 91de353..1b308aa 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -15,7 +15,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk"
     ],
 
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 52213bd..390ba43 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -44,10 +44,9 @@
 #include <media/stagefright/foundation/ColorUtils.h>
 #include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaBufferBase.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/String8.h>
 
 #include <byteswap.h>
@@ -70,7 +69,7 @@
     kMaxAtomSize = 64 * 1024 * 1024,
 };
 
-class MPEG4Source : public MediaTrackHelperV2 {
+class MPEG4Source : public MediaTrackHelperV3 {
 static const size_t  kMaxPcmFrameSize = 8192;
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
@@ -89,10 +88,10 @@
 
     virtual media_status_t getFormat(AMediaFormat *);
 
-    virtual media_status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
+    virtual media_status_t read(MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
     virtual bool supportNonblockingRead() { return true; }
     virtual media_status_t fragmentedRead(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
     virtual ~MPEG4Source();
 
@@ -137,9 +136,7 @@
 
     bool mStarted;
 
-    MediaBufferGroup *mGroup;
-
-    MediaBufferBase *mBuffer;
+    MediaBufferHelperV3 *mBuffer;
 
     uint8_t *mSrcBuffer;
 
@@ -1556,9 +1553,40 @@
                 return ERROR_IO;
             }
 
-            String8 mimeFormat((const char *)(buffer.get()), chunk_data_size);
-            AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+            // Prior to API 29, the metadata track was not compliant with ISO/IEC
+            // 14496-12-2015. This led to some ISO-compliant parsers failing to read the
+            // metatrack. As of API 29 and onwards, a change was made to metadata track to
+            // make it compliant with the standard. The workaround is to write the
+            // null-terminated mime_format string twice. This allows compliant parsers to
+            // read the missing reserved, data_reference_index, and content_encoding fields
+            // from the first mime_type string. The actual mime_format field would then be
+            // read correctly from the second string. The non-compliant Android frameworks
+            // from API 28 and earlier would still be able to read the mime_format correctly
+            // as it would only read the first null-terminated mime_format string. To enable
+            // reading metadata tracks generated from both the non-compliant and compliant
+            // formats, a check needs to be done to see which format is used.
+            int null_pos = 0;
+            const unsigned char *str = buffer.get();
+            while (null_pos < chunk_data_size) {
+              if (*(str + null_pos) == '\0') {
+                break;
+              }
+              ++null_pos;
+            }
 
+            if (null_pos == chunk_data_size - 1) {
+              // This is not a standard ompliant metadata track.
+              String8 mimeFormat((const char *)(buffer.get()), chunk_data_size);
+              AMediaFormat_setString(mLastTrack->meta,
+                  AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+            } else {
+              // This is a standard compliant metadata track.
+              String8 contentEncoding((const char *)(buffer.get() + 8));
+              String8 mimeFormat((const char *)(buffer.get() + 8 + contentEncoding.size() + 1),
+                  chunk_data_size - 8 - contentEncoding.size() - 1);
+              AMediaFormat_setString(mLastTrack->meta,
+                  AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+            }
             break;
         }
 
@@ -3827,7 +3855,7 @@
     }
 }
 
-MediaTrackHelperV2 *MPEG4Extractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
@@ -4329,7 +4357,6 @@
       mIsPcm(false),
       mNALLengthSize(0),
       mStarted(false),
-      mGroup(NULL),
       mBuffer(NULL),
       mSrcBuffer(NULL),
       mIsHeif(itemTable != NULL),
@@ -4458,12 +4485,10 @@
     const size_t kInitialBuffers = 2;
     const size_t kMaxBuffers = 8;
     const size_t realMaxBuffers = min(kMaxBufferSize / max_size, kMaxBuffers);
-    mGroup = new MediaBufferGroup(kInitialBuffers, max_size, realMaxBuffers);
+    mBufferGroup->init(kInitialBuffers, max_size, realMaxBuffers);
     mSrcBuffer = new (std::nothrow) uint8_t[max_size];
     if (mSrcBuffer == NULL) {
         // file probably specified a bad max size
-        delete mGroup;
-        mGroup = NULL;
         return AMEDIA_ERROR_MALFORMED;
     }
 
@@ -4485,9 +4510,6 @@
     delete[] mSrcBuffer;
     mSrcBuffer = NULL;
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
     mCurrentSampleIndex = 0;
 
@@ -5184,12 +5206,12 @@
 }
 
 media_status_t MPEG4Source::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     Mutex::Autolock autoLock(mLock);
 
     CHECK(mStarted);
 
-    if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) {
+    if (options != nullptr && options->getNonBlocking() && !mBufferGroup->has_buffers()) {
         *out = nullptr;
         return AMEDIA_ERROR_WOULD_BLOCK;
     }
@@ -5338,7 +5360,7 @@
             return AMEDIA_ERROR_UNKNOWN;
         }
 
-        err = mGroup->acquire_buffer(&mBuffer);
+        err = mBufferGroup->acquire_buffer(&mBuffer);
 
         if (err != OK) {
             CHECK(mBuffer == NULL);
@@ -5377,9 +5399,11 @@
                     return AMEDIA_ERROR_IO;
                 }
 
-                mBuffer->meta_data().clear();
-                mBuffer->meta_data().setInt64(kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-                mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+                AMediaFormat *meta = mBuffer->meta_data();
+                AMediaFormat_clear(meta);
+                AMediaFormat_setInt64(
+                      meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
                 int32_t byteOrder;
                 AMediaFormat_getInt32(mFormat,
@@ -5410,19 +5434,20 @@
 
                 CHECK(mBuffer != NULL);
                 mBuffer->set_range(0, size);
-                mBuffer->meta_data().clear();
-                mBuffer->meta_data().setInt64(
-                        kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-                mBuffer->meta_data().setInt64(
-                        kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+                AMediaFormat *meta = mBuffer->meta_data();
+                AMediaFormat_clear(meta);
+                AMediaFormat_setInt64(
+                        meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+                AMediaFormat_setInt64(
+                        meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
 
                 if (targetSampleTimeUs >= 0) {
-                    mBuffer->meta_data().setInt64(
-                            kKeyTargetTime, targetSampleTimeUs);
+                    AMediaFormat_setInt64(
+                            meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
                 }
 
                 if (isSyncSample) {
-                    mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+                    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
                 }
  
                 ++mCurrentSampleIndex;
@@ -5465,19 +5490,20 @@
         }
 
         mBuffer->set_range(0, dstOffset + size);
-        mBuffer->meta_data().clear();
-        mBuffer->meta_data().setInt64(
-                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-        mBuffer->meta_data().setInt64(
-                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+        AMediaFormat *meta = mBuffer->meta_data();
+        AMediaFormat_clear(meta);
+        AMediaFormat_setInt64(
+                meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+        AMediaFormat_setInt64(
+                meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
-            mBuffer->meta_data().setInt64(
-                    kKeyTargetTime, targetSampleTimeUs);
+            AMediaFormat_setInt64(
+                    meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
         }
 
         if (isSyncSample) {
-            mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+            AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
         }
 
         ++mCurrentSampleIndex;
@@ -5545,31 +5571,32 @@
         CHECK(mBuffer != NULL);
         mBuffer->set_range(0, dstOffset);
 
-        mBuffer->meta_data().clear();
-        mBuffer->meta_data().setInt64(
-                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-        mBuffer->meta_data().setInt64(
-                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+        AMediaFormat *meta = mBuffer->meta_data();
+        AMediaFormat_clear(meta);
+        AMediaFormat_setInt64(
+                meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+        AMediaFormat_setInt64(
+                meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
-            mBuffer->meta_data().setInt64(
-                    kKeyTargetTime, targetSampleTimeUs);
+            AMediaFormat_setInt64(
+                    meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
         }
 
         if (mIsAVC) {
             uint32_t layerId = FindAVCLayerId(
                     (const uint8_t *)mBuffer->data(), mBuffer->range_length());
-            mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+            AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
         } else if (mIsHEVC) {
             int32_t layerId = parseHEVCLayerId(
                     (const uint8_t *)mBuffer->data(), mBuffer->range_length());
             if (layerId >= 0) {
-                mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
             }
         }
 
         if (isSyncSample) {
-            mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+            AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
         }
 
         ++mCurrentSampleIndex;
@@ -5582,7 +5609,7 @@
 }
 
 media_status_t MPEG4Source::fragmentedRead(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
 
     ALOGV("MPEG4Source::fragmentedRead");
 
@@ -5685,7 +5712,7 @@
         mCurrentTime += smpl->duration;
         isSyncSample = (mCurrentSampleIndex == 0);
 
-        status_t err = mGroup->acquire_buffer(&mBuffer);
+        status_t err = mBufferGroup->acquire_buffer(&mBuffer);
 
         if (err != OK) {
             CHECK(mBuffer == NULL);
@@ -5701,19 +5728,21 @@
     }
 
     const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
-    MetaDataBase &bufmeta = mBuffer->meta_data();
-    bufmeta.clear();
+    AMediaFormat *bufmeta = mBuffer->meta_data();
+    AMediaFormat_clear(bufmeta);
     if (smpl->encryptedsizes.size()) {
         // store clear/encrypted lengths in metadata
-        bufmeta.setData(kKeyPlainSizes, 0,
+        AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
                 smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
-        bufmeta.setData(kKeyEncryptedSizes, 0,
+        AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
                 smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
-        bufmeta.setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
-        bufmeta.setInt32(kKeyCryptoMode, mCryptoMode);
-        bufmeta.setData(kKeyCryptoKey, 0, mCryptoKey, 16);
-        bufmeta.setInt32(kKeyEncryptedByteBlock, mDefaultEncryptedByteBlock);
-        bufmeta.setInt32(kKeySkipByteBlock, mDefaultSkipByteBlock);
+        AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, mDefaultIVSize);
+        AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_MODE, mCryptoMode);
+        AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_KEY, mCryptoKey, 16);
+        AMediaFormat_setInt32(bufmeta,
+                AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK, mDefaultEncryptedByteBlock);
+        AMediaFormat_setInt32(bufmeta,
+                AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK, mDefaultSkipByteBlock);
 
         void *iv = NULL;
         size_t ivlength = 0;
@@ -5722,8 +5751,7 @@
             iv = (void *) smpl->iv;
             ivlength = 16; // use 16 or the actual size?
         }
-        bufmeta.setData(kKeyCryptoIV, 0, iv, ivlength);
-
+        AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_IV, iv, ivlength);
     }
 
     if (!mIsAVC && !mIsHEVC) {
@@ -5749,30 +5777,29 @@
 
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
-            mBuffer->meta_data().setInt64(
-                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-            mBuffer->meta_data().setInt64(
-                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
+            AMediaFormat_setInt64(bufmeta,
+                    AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+            AMediaFormat_setInt64(bufmeta,
+                    AMEDIAFORMAT_KEY_DURATION, ((int64_t)smpl->duration * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
-                mBuffer->meta_data().setInt64(
-                        kKeyTargetTime, targetSampleTimeUs);
+                AMediaFormat_setInt64(bufmeta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
             }
 
             if (mIsAVC) {
                 uint32_t layerId = FindAVCLayerId(
                         (const uint8_t *)mBuffer->data(), mBuffer->range_length());
-                mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+                AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
             } else if (mIsHEVC) {
                 int32_t layerId = parseHEVCLayerId(
                         (const uint8_t *)mBuffer->data(), mBuffer->range_length());
                 if (layerId >= 0) {
-                    mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+                    AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
                 }
             }
 
             if (isSyncSample) {
-                mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+                AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
             }
 
             ++mCurrentSampleIndex;
@@ -5864,18 +5891,18 @@
         CHECK(mBuffer != NULL);
         mBuffer->set_range(0, dstOffset);
 
-        mBuffer->meta_data().setInt64(
-                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-        mBuffer->meta_data().setInt64(
-                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
+        AMediaFormat *bufmeta = mBuffer->meta_data();
+        AMediaFormat_setInt64(bufmeta,
+                AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+        AMediaFormat_setInt64(bufmeta,
+                AMEDIAFORMAT_KEY_DURATION, ((int64_t)smpl->duration * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
-            mBuffer->meta_data().setInt64(
-                    kKeyTargetTime, targetSampleTimeUs);
+            AMediaFormat_setInt64(bufmeta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
         }
 
         if (isSyncSample) {
-            mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+            AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
         }
 
         ++mCurrentSampleIndex;
@@ -6075,11 +6102,11 @@
     return true;
 }
 
-static CMediaExtractorV2* CreateExtractor(CDataSource *source, void *) {
-    return wrapV2(new MPEG4Extractor(new DataSourceHelper(source)));
+static CMediaExtractorV3* CreateExtractor(CDataSource *source, void *) {
+    return wrapV3(new MPEG4Extractor(new DataSourceHelper(source)));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source, float *confidence, void **,
         FreeMetaFunc *) {
     DataSourceHelper helper(source);
@@ -6100,11 +6127,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
         2, // version
         "MP4 Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 56b641d..a9a4635 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -53,12 +53,12 @@
     uint32_t default_sample_flags;
 };
 
-class MPEG4Extractor : public MediaExtractorPluginHelperV2 {
+class MPEG4Extractor : public MediaExtractorPluginHelperV3 {
 public:
     explicit MPEG4Extractor(DataSourceHelper *source, const char *mime = NULL);
 
     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/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 38c86eb..b816093 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -15,14 +15,11 @@
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
         "android.hidl.token@1.0-utils",
-        "libbinder",
-        "libcrypto",
-        "libcutils",
-        "libhidlallocatorutils",
+        "android.hidl.allocator@1.0",
+        "libhidlmemory",
         "libhidlbase",
         "liblog",
-        "libmediaextractor",
-        "libstagefright_foundation",
+        "libmediandk",
     ],
 
     header_libs: [
@@ -30,8 +27,13 @@
     ],
 
     static_libs: [
+        "libcrypto",
+        "libstagefright_foundation",
         "libstagefright_mpeg2support",
+        "libmediaextractor",
         "libutils",
+        "libstagefright",
+        "libstagefright_esds",
     ],
 
     name: "libmpeg2extractor",
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 366aa59..c10a797 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -31,27 +31,27 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("3d1dcfeb-e40a-436d-a574-c2438a555e5f"),
         1,
         "MPEG2-PS/TS Extractor",
         {
-            [](
+            .v3 = [](
                     CDataSource *source,
                     float *confidence,
                     void **,
-                    FreeMetaFunc *) -> CreatorFunc {
+                    FreeMetaFunc *) -> CreatorFuncV3 {
                 DataSourceHelper helper(source);
                 if (SniffMPEG2TS(&helper, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractor* {
-                        return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new MPEG2TSExtractor(new DataSourceHelper(source)));};
                 } else if (SniffMPEG2PS(&helper, confidence)) {
                             return [](
                                     CDataSource *source,
-                                    void *) -> CMediaExtractor* {
-                                return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
+                                    void *) -> CMediaExtractorV3* {
+                                return wrapV3(new MPEG2PSExtractor(new DataSourceHelper(source)));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index fc13d2c..b60fc4e 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -33,22 +33,23 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
 #include <utils/String8.h>
 
 #include <inttypes.h>
 
 namespace android {
 
-struct MPEG2PSExtractor::Track : public MediaTrackHelper, public RefBase {
+struct MPEG2PSExtractor::Track : public MediaTrackHelperV3 {
     Track(MPEG2PSExtractor *extractor,
           unsigned stream_id, unsigned stream_type);
 
-    virtual status_t start();
-    virtual status_t stop();
-    virtual status_t getFormat(MetaDataBase &);
+    virtual media_status_t start();
+    virtual media_status_t stop();
+    virtual media_status_t getFormat(AMediaFormat *);
 
-    virtual status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options);
+    virtual media_status_t read(
+            MediaBufferHelperV3 **buffer, const ReadOptions *options);
 
 protected:
     virtual ~Track();
@@ -71,22 +72,22 @@
     DISALLOW_EVIL_CONSTRUCTORS(Track);
 };
 
-struct MPEG2PSExtractor::WrappedTrack : public MediaTrackHelper {
-    WrappedTrack(MPEG2PSExtractor *extractor, const sp<Track> &track);
+struct MPEG2PSExtractor::WrappedTrack : public MediaTrackHelperV3 {
+    WrappedTrack(MPEG2PSExtractor *extractor, Track *track);
 
-    virtual status_t start();
-    virtual status_t stop();
-    virtual status_t getFormat(MetaDataBase &);
+    virtual media_status_t start();
+    virtual media_status_t stop();
+    virtual media_status_t getFormat(AMediaFormat *);
 
-    virtual status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options);
+    virtual media_status_t read(
+            MediaBufferHelperV3 **buffer, const ReadOptions *options);
 
 protected:
     virtual ~WrappedTrack();
 
 private:
     MPEG2PSExtractor *mExtractor;
-    sp<MPEG2PSExtractor::Track> mTrack;
+    MPEG2PSExtractor::Track *mTrack;
 
     DISALLOW_EVIL_CONSTRUCTORS(WrappedTrack);
 };
@@ -107,13 +108,14 @@
     }
 
     // Remove all tracks that were unable to determine their format.
-    MetaDataBase meta;
+    AMediaFormat *meta = AMediaFormat_new();
     for (size_t i = mTracks.size(); i > 0;) {
         i--;
-        if (mTracks.valueAt(i)->getFormat(meta) != OK) {
+        if (mTracks.valueAt(i)->getFormat(meta) != AMEDIA_OK) {
             mTracks.removeItemsAt(i);
         }
     }
+    AMediaFormat_delete(meta);
 
     mScanning = false;
 }
@@ -126,7 +128,7 @@
     return mTracks.size();
 }
 
-MediaTrackHelper *MPEG2PSExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MPEG2PSExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
@@ -134,20 +136,20 @@
     return new WrappedTrack(this, mTracks.valueAt(index));
 }
 
-status_t MPEG2PSExtractor::getTrackMetaData(
-        MetaDataBase &meta,
+media_status_t MPEG2PSExtractor::getTrackMetaData(
+        AMediaFormat *meta,
         size_t index, uint32_t /* flags */) {
     if (index >= mTracks.size()) {
-        return UNKNOWN_ERROR;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
     return mTracks.valueAt(index)->getFormat(meta);
 }
 
-status_t MPEG2PSExtractor::getMetaData(MetaDataBase &meta) {
-    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
+media_status_t MPEG2PSExtractor::getMetaData(AMediaFormat *meta) {
+    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
 
-    return OK;
+    return AMEDIA_OK;
 }
 
 uint32_t MPEG2PSExtractor::flags() const {
@@ -635,42 +637,55 @@
     mQueue = NULL;
 }
 
-status_t MPEG2PSExtractor::Track::start() {
+media_status_t MPEG2PSExtractor::Track::start() {
     if (mSource == NULL) {
-        return NO_INIT;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
-    return mSource->start(NULL); // AnotherPacketSource::start doesn't use its argument
+    // initialize with one small buffer, but allow growth
+    mBufferGroup->init(1 /* one buffer */, 256 /* buffer size */, 64 /* max number of buffers */);
+
+    if (mSource->start(NULL) == OK) { // AnotherPacketSource::start doesn't use its argument
+        return AMEDIA_OK;
+    }
+    return AMEDIA_ERROR_UNKNOWN;
 }
 
-status_t MPEG2PSExtractor::Track::stop() {
+media_status_t MPEG2PSExtractor::Track::stop() {
     if (mSource == NULL) {
-        return NO_INIT;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
-    return mSource->stop();
+    if (mSource->stop() == OK) {
+        return AMEDIA_OK;
+    }
+    return AMEDIA_ERROR_UNKNOWN;
 }
 
-status_t MPEG2PSExtractor::Track::getFormat(MetaDataBase &meta) {
+void copyAMessageToAMediaFormat(AMediaFormat *format, sp<AMessage> msg);
+
+media_status_t MPEG2PSExtractor::Track::getFormat(AMediaFormat *meta) {
     if (mSource == NULL) {
-        return NO_INIT;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
     sp<MetaData> sourceMeta = mSource->getFormat();
-    meta = *sourceMeta;
-    return OK;
+    sp<AMessage> msg;
+    convertMetaDataToMessage(sourceMeta, &msg);
+    copyAMessageToAMediaFormat(meta, msg);
+    return AMEDIA_OK;
 }
 
-status_t MPEG2PSExtractor::Track::read(
-        MediaBufferBase **buffer, const ReadOptions *options) {
+media_status_t MPEG2PSExtractor::Track::read(
+        MediaBufferHelperV3 **buffer, const ReadOptions *options) {
     if (mSource == NULL) {
-        return NO_INIT;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
     status_t finalResult;
     while (!mSource->hasBufferAvailable(&finalResult)) {
         if (finalResult != OK) {
-            return ERROR_END_OF_STREAM;
+            return AMEDIA_ERROR_END_OF_STREAM;
         }
 
         status_t err = mExtractor->feedMore();
@@ -680,7 +695,46 @@
         }
     }
 
-    return mSource->read(buffer, (MediaSource::ReadOptions*)options);
+    MediaBufferBase *mbuf;
+    mSource->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    size_t length = mbuf->range_length();
+    MediaBufferHelperV3 *outbuf;
+    mBufferGroup->acquire_buffer(&outbuf, false, length);
+    memcpy(outbuf->data(), mbuf->data(), length);
+    outbuf->set_range(0, length);
+    *buffer = outbuf;
+    MetaDataBase &inMeta = mbuf->meta_data();
+    AMediaFormat *outMeta = outbuf->meta_data();
+    int64_t val64;
+    if (inMeta.findInt64(kKeyTime, &val64)) {
+        AMediaFormat_setInt64(outMeta, AMEDIAFORMAT_KEY_TIME_US, val64);
+    }
+    int32_t val32;
+    if (inMeta.findInt32(kKeyIsSyncFrame, &val32)) {
+        AMediaFormat_setInt32(outMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, val32);
+    }
+    if (inMeta.findInt32(kKeyCryptoMode, &val32)) {
+        AMediaFormat_setInt32(outMeta, AMEDIAFORMAT_KEY_CRYPTO_MODE, val32);
+    }
+    uint32_t bufType;
+    const void *bufData;
+    size_t bufSize;
+    if (inMeta.findData(kKeyCryptoIV, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_IV, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyCryptoKey, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyPlainSizes, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyEncryptedSizes, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
+    }
+    return AMEDIA_OK;
 }
 
 status_t MPEG2PSExtractor::Track::appendPESData(
@@ -726,7 +780,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG2PSExtractor::WrappedTrack::WrappedTrack(
-        MPEG2PSExtractor *extractor, const sp<Track> &track)
+        MPEG2PSExtractor *extractor, Track *track)
     : mExtractor(extractor),
       mTrack(track) {
 }
@@ -734,20 +788,20 @@
 MPEG2PSExtractor::WrappedTrack::~WrappedTrack() {
 }
 
-status_t MPEG2PSExtractor::WrappedTrack::start() {
+media_status_t MPEG2PSExtractor::WrappedTrack::start() {
     return mTrack->start();
 }
 
-status_t MPEG2PSExtractor::WrappedTrack::stop() {
+media_status_t MPEG2PSExtractor::WrappedTrack::stop() {
     return mTrack->stop();
 }
 
-status_t MPEG2PSExtractor::WrappedTrack::getFormat(MetaDataBase &meta) {
+media_status_t MPEG2PSExtractor::WrappedTrack::getFormat(AMediaFormat *meta) {
     return mTrack->getFormat(meta);
 }
 
-status_t MPEG2PSExtractor::WrappedTrack::read(
-        MediaBufferBase **buffer, const ReadOptions *options) {
+media_status_t MPEG2PSExtractor::WrappedTrack::read(
+        MediaBufferHelperV3 **buffer, const ReadOptions *options) {
     return mTrack->read(buffer, options);
 }
 
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index c4082ef..d251688 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -32,14 +32,14 @@
 struct Track;
 class String8;
 
-struct MPEG2PSExtractor : public MediaExtractorPluginHelper {
+struct MPEG2PSExtractor : public MediaExtractorPluginHelperV3 {
     explicit MPEG2PSExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelper *getTrack(size_t index);
-    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
+    virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
-    virtual status_t getMetaData(MetaDataBase& meta);
+    virtual media_status_t getMetaData(AMediaFormat *meta);
 
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2PSExtractor"; }
@@ -57,7 +57,7 @@
     off64_t mOffset;
     status_t mFinalResult;
     sp<ABuffer> mBuffer;
-    KeyedVector<unsigned, sp<Track> > mTracks;
+    KeyedVector<unsigned, Track* > mTracks;
     bool mScanning;
 
     bool mProgramStreamMapValid;
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 605b13a..fc066ee 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -34,6 +34,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
 #include <utils/String8.h>
 
 #include "mpeg2ts/AnotherPacketSource.h"
@@ -50,19 +51,19 @@
 static const int kMaxDurationReadSize = 250000LL;
 static const int kMaxDurationRetry = 6;
 
-struct MPEG2TSSource : public MediaTrackHelper {
+struct MPEG2TSSource : public MediaTrackHelperV3 {
     MPEG2TSSource(
             MPEG2TSExtractor *extractor,
             const sp<AnotherPacketSource> &impl,
             bool doesSeek);
     virtual ~MPEG2TSSource();
 
-    virtual status_t start();
-    virtual status_t stop();
-    virtual status_t getFormat(MetaDataBase &);
+    virtual media_status_t start();
+    virtual media_status_t stop();
+    virtual media_status_t getFormat(AMediaFormat *);
 
-    virtual status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+    virtual media_status_t read(
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 private:
     MPEG2TSExtractor *mExtractor;
@@ -87,22 +88,84 @@
 MPEG2TSSource::~MPEG2TSSource() {
 }
 
-status_t MPEG2TSSource::start() {
-    return mImpl->start(NULL); // AnotherPacketSource::start() doesn't use its argument
+media_status_t MPEG2TSSource::start() {
+    // initialize with one small buffer, but allow growth
+    mBufferGroup->init(1 /* one buffer */, 256 /* buffer size */, 64 /* max number of buffers */);
+
+    if (!mImpl->start(NULL)) { // AnotherPacketSource::start() doesn't use its argument
+        return AMEDIA_OK;
+    }
+    return AMEDIA_ERROR_UNKNOWN;
 }
 
-status_t MPEG2TSSource::stop() {
-    return mImpl->stop();
+media_status_t MPEG2TSSource::stop() {
+    if (!mImpl->stop()) {
+        return AMEDIA_OK;
+    }
+    return AMEDIA_ERROR_UNKNOWN;
 }
 
-status_t MPEG2TSSource::getFormat(MetaDataBase &meta) {
+void copyAMessageToAMediaFormat(AMediaFormat *format, sp<AMessage> msg) {
+    size_t numEntries = msg->countEntries();
+    for (size_t i = 0; i < numEntries; i++) {
+        AMessage::Type type;
+        const char *name = msg->getEntryNameAt(i, &type);
+        AMessage::ItemData id = msg->getEntryAt(i);
+
+        switch (type) {
+            case AMessage::kTypeInt32:
+                int32_t val32;
+                if (id.find(&val32)) {
+                    AMediaFormat_setInt32(format, name, val32);
+                }
+                break;
+            case AMessage::kTypeInt64:
+                int64_t val64;
+                if (id.find(&val64)) {
+                    AMediaFormat_setInt64(format, name, val64);
+                }
+                break;
+            case AMessage::kTypeFloat:
+                float valfloat;
+                if (id.find(&valfloat)) {
+                    AMediaFormat_setFloat(format, name, valfloat);
+                }
+                break;
+            case AMessage::kTypeDouble:
+                double valdouble;
+                if (id.find(&valdouble)) {
+                    AMediaFormat_setDouble(format, name, valdouble);
+                }
+                break;
+            case AMessage::kTypeString:
+                if (AString s; id.find(&s)) {
+                    AMediaFormat_setString(format, name, s.c_str());
+                }
+                break;
+            case AMessage::kTypeBuffer:
+            {
+                sp<ABuffer> buffer;
+                if (id.find(&buffer)) {
+                    AMediaFormat_setBuffer(format, name, buffer->data(), buffer->size());
+                }
+                break;
+            }
+            default:
+                ALOGW("ignoring unsupported type %d '%s'", type, name);
+        }
+    }
+}
+
+media_status_t MPEG2TSSource::getFormat(AMediaFormat *meta) {
     sp<MetaData> implMeta = mImpl->getFormat();
-    meta = *implMeta;
-    return OK;
+    sp<AMessage> msg;
+    convertMetaDataToMessage(implMeta, &msg);
+    copyAMessageToAMediaFormat(meta, msg);
+    return AMEDIA_OK;
 }
 
-status_t MPEG2TSSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+media_status_t MPEG2TSSource::read(
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -110,16 +173,59 @@
     if (mDoesSeek && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
         // seek is needed
         status_t err = mExtractor->seek(seekTimeUs, (ReadOptions::SeekMode)seekMode);
-        if (err != OK) {
-            return err;
+        if (err == ERROR_END_OF_STREAM) {
+            return AMEDIA_ERROR_END_OF_STREAM;
+        } else if (err != OK) {
+            return AMEDIA_ERROR_UNKNOWN;
         }
     }
 
     if (mExtractor->feedUntilBufferAvailable(mImpl) != OK) {
-        return ERROR_END_OF_STREAM;
+        return AMEDIA_ERROR_END_OF_STREAM;
     }
 
-    return mImpl->read(out, (MediaSource::ReadOptions*) options);
+    MediaBufferBase *mbuf;
+    mImpl->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    size_t length = mbuf->range_length();
+    MediaBufferHelperV3 *outbuf;
+    mBufferGroup->acquire_buffer(&outbuf, false, length);
+    memcpy(outbuf->data(), mbuf->data(), length);
+    outbuf->set_range(0, length);
+    *out = outbuf;
+    MetaDataBase &inMeta = mbuf->meta_data();
+    AMediaFormat *outMeta = outbuf->meta_data();
+    AMediaFormat_clear(outMeta);
+    int64_t val64;
+    if (inMeta.findInt64(kKeyTime, &val64)) {
+        AMediaFormat_setInt64(outMeta, AMEDIAFORMAT_KEY_TIME_US, val64);
+    }
+    int32_t val32;
+    if (inMeta.findInt32(kKeyIsSyncFrame, &val32)) {
+        AMediaFormat_setInt32(outMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, val32);
+    }
+    if (inMeta.findInt32(kKeyCryptoMode, &val32)) {
+        AMediaFormat_setInt32(outMeta, AMEDIAFORMAT_KEY_CRYPTO_MODE, val32);
+    }
+    uint32_t bufType;
+    const void *bufData;
+    size_t bufSize;
+    if (inMeta.findData(kKeyCryptoIV, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_IV, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyCryptoKey, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyPlainSizes, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeyEncryptedSizes, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES, bufData, bufSize);
+    }
+    if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
+        AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
+    }
+
+    return AMEDIA_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -140,7 +246,7 @@
     return mSourceImpls.size();
 }
 
-MediaTrackHelper *MPEG2TSExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MPEG2TSExtractor::getTrack(size_t index) {
     if (index >= mSourceImpls.size()) {
         return NULL;
     }
@@ -151,22 +257,23 @@
             (mSeekSyncPoints == &mSyncPoints.editItemAt(index)));
 }
 
-status_t MPEG2TSExtractor::getTrackMetaData(
-        MetaDataBase &meta,
+media_status_t MPEG2TSExtractor::getTrackMetaData(
+        AMediaFormat *meta,
         size_t index, uint32_t /* flags */) {
     sp<MetaData> implMeta = index < mSourceImpls.size()
         ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
     if (implMeta == NULL) {
-        return UNKNOWN_ERROR;
+        return AMEDIA_ERROR_UNKNOWN;
     }
-    meta = *implMeta;
-    return OK;
+    sp<AMessage> msg = new AMessage;
+    convertMetaDataToMessage(implMeta, &msg);
+    copyAMessageToAMediaFormat(meta, msg);
+    return AMEDIA_OK;
 }
 
-status_t MPEG2TSExtractor::getMetaData(MetaDataBase &meta) {
-    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
-
-    return OK;
+media_status_t MPEG2TSExtractor::getMetaData(AMediaFormat *meta) {
+    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+    return AMEDIA_OK;
 }
 
 //static
@@ -177,7 +284,7 @@
                     || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
 }
 
-status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
+media_status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
     HalToken halToken;
     halToken.setToExternal((uint8_t*)casToken, size);
     sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
@@ -187,8 +294,9 @@
     if (err == OK) {
         ALOGI("All tracks now have descramblers");
         init();
+        return AMEDIA_OK;
     }
-    return err;
+    return AMEDIA_ERROR_UNKNOWN;
 }
 
 void MPEG2TSExtractor::addSource(const sp<AnotherPacketSource> &impl) {
@@ -494,7 +602,7 @@
 }
 
 status_t MPEG2TSExtractor::seek(int64_t seekTimeUs,
-        const MediaTrackHelper::ReadOptions::SeekMode &seekMode) {
+        const MediaTrackHelperV3::ReadOptions::SeekMode &seekMode) {
     if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) {
         ALOGW("No sync point to seek to.");
         // ... and therefore we have nothing useful to do here.
@@ -515,18 +623,18 @@
     }
 
     switch (seekMode) {
-        case MediaTrackHelper::ReadOptions::SEEK_NEXT_SYNC:
+        case MediaTrackHelperV3::ReadOptions::SEEK_NEXT_SYNC:
             if (index == mSeekSyncPoints->size()) {
                 ALOGW("Next sync not found; starting from the latest sync.");
                 --index;
             }
             break;
-        case MediaTrackHelper::ReadOptions::SEEK_CLOSEST_SYNC:
-        case MediaTrackHelper::ReadOptions::SEEK_CLOSEST:
+        case MediaTrackHelperV3::ReadOptions::SEEK_CLOSEST_SYNC:
+        case MediaTrackHelperV3::ReadOptions::SEEK_CLOSEST:
             ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC",
                     seekMode);
             FALLTHROUGH_INTENDED;
-        case MediaTrackHelper::ReadOptions::SEEK_PREVIOUS_SYNC:
+        case MediaTrackHelperV3::ReadOptions::SEEK_PREVIOUS_SYNC:
             if (index == 0) {
                 ALOGW("Previous sync not found; starting from the earliest "
                         "sync.");
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 4013442..aed17bb 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -38,16 +38,16 @@
 struct MPEG2TSSource;
 class String8;
 
-struct MPEG2TSExtractor : public MediaExtractorPluginHelper {
+struct MPEG2TSExtractor : public MediaExtractorPluginHelperV3 {
     explicit MPEG2TSExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelper *getTrack(size_t index);
-    virtual status_t getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t flags);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
+    virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
-    virtual status_t getMetaData(MetaDataBase& meta);
+    virtual media_status_t getMetaData(AMediaFormat *meta);
 
-    virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
+    virtual media_status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
 
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2TSExtractor"; }
@@ -90,7 +90,7 @@
     // the data has syntax error during parsing, etc.
     status_t feedMore(bool isInit = false);
     status_t seek(int64_t seekTimeUs,
-            const MediaTrackHelper::ReadOptions::SeekMode& seekMode);
+            const MediaTrackHelperV3::ReadOptions::SeekMode& seekMode);
     status_t queueDiscontinuityForSeek(int64_t actualSeekTimeUs);
     status_t seekBeyond(int64_t seekTimeUs);
 
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index b28877d..604ec59 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -13,7 +13,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index cc2c792..29fe2b1 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -28,11 +28,8 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/foundation/ByteUtils.h>
-#include <media/stagefright/MediaBufferBase.h>
-#include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaDataBase.h>
 #include <media/stagefright/MetaDataUtils.h>
 #include <system/audio.h>
 #include <utils/String8.h>
@@ -48,7 +45,7 @@
 
 namespace android {
 
-struct OggSource : public MediaTrackHelperV2 {
+struct OggSource : public MediaTrackHelperV3 {
     explicit OggSource(OggExtractor *extractor);
 
     virtual media_status_t getFormat(AMediaFormat *);
@@ -57,7 +54,7 @@
     virtual media_status_t stop();
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~OggSource();
@@ -85,7 +82,7 @@
 
     status_t seekToTime(int64_t timeUs);
     status_t seekToOffset(off64_t offset);
-    virtual media_status_t readNextPacket(MediaBufferBase **buffer) = 0;
+    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer) = 0;
 
     status_t init();
 
@@ -93,6 +90,9 @@
         return AMediaFormat_copy(meta, mFileMeta);
     }
 
+    void setBufferGroup(MediaBufferGroupHelperV3 *group) {
+        mBufferGroup = group;
+    }
 protected:
     struct Page {
         uint64_t mGranulePosition;
@@ -110,6 +110,7 @@
         int64_t mTimeUs;
     };
 
+    MediaBufferGroupHelperV3 *mBufferGroup;
     DataSourceHelper *mSource;
     off64_t mOffset;
     Page mCurrentPage;
@@ -148,7 +149,7 @@
     // 1 - bitstream identification header
     // 3 - comment header
     // 5 - codec setup header (Vorbis only)
-    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0;
+    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type) = 0;
 
     // Read the next ogg packet from the underlying data source; optionally
     // calculate the timestamp for the output packet whilst pretending
@@ -156,9 +157,9 @@
     //
     // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated;
     // clients are responsible for releasing the original buffer.
-    media_status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp);
+    media_status_t _readNextPacket(MediaBufferHelperV3 **buffer, bool calcVorbisTimestamp);
 
-    int32_t getPacketBlockSize(MediaBufferBase *buffer);
+    int32_t getPacketBlockSize(MediaBufferHelperV3 *buffer);
 
     void parseFileMetaData();
 
@@ -182,7 +183,7 @@
 
     virtual uint64_t approxBitrate() const;
 
-    virtual media_status_t readNextPacket(MediaBufferBase **buffer) {
+    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer) {
         return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true);
     }
 
@@ -194,7 +195,7 @@
         return granulePos * 1000000ll / mVi.rate;
     }
 
-    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type);
+    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type);
 };
 
 struct MyOpusExtractor : public MyOggExtractor {
@@ -212,16 +213,16 @@
         return 0;
     }
 
-    virtual media_status_t readNextPacket(MediaBufferBase **buffer);
+    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer);
 
 protected:
     virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
-    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type);
+    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type);
 
 private:
-    media_status_t verifyOpusHeader(MediaBufferBase *buffer);
-    media_status_t verifyOpusComments(MediaBufferBase *buffer);
-    uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const;
+    media_status_t verifyOpusHeader(MediaBufferHelperV3 *buffer);
+    media_status_t verifyOpusComments(MediaBufferHelperV3 *buffer);
+    uint32_t getNumSamplesInPacket(MediaBufferHelperV3 *buffer) const;
 
     uint8_t mChannelCount;
     uint16_t mCodecDelay;
@@ -249,7 +250,9 @@
     if (mStarted) {
         return AMEDIA_ERROR_INVALID_OPERATION;
     }
-
+    // initialize buffer group with a single small buffer, but a generous upper limit
+    mBufferGroup->init(1 /* number of buffers */, 128 /* size */, 64 /* max number of buffers */);
+    mExtractor->mImpl->setBufferGroup(mBufferGroup);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -262,7 +265,7 @@
 }
 
 media_status_t OggSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -274,26 +277,27 @@
         }
     }
 
-    MediaBufferBase *packet;
+    MediaBufferHelperV3 *packet;
     media_status_t err = mExtractor->mImpl->readNextPacket(&packet);
 
     if (err != AMEDIA_OK) {
         return err;
     }
 
+    AMediaFormat *meta = packet->meta_data();
 #if 0
     int64_t timeUs;
-    if (packet->meta_data().findInt64(kKeyTime, &timeUs)) {
+    if (AMediaFormat_findInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeStampUs)) {
         ALOGI("found time = %lld us", timeUs);
     } else {
         ALOGI("NO time");
     }
 #endif
 
-    packet->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     *out = packet;
-
+    ALOGV("returning buffer %p", packet);
     return AMEDIA_OK;
 }
 
@@ -304,7 +308,8 @@
         const char *mimeType,
         size_t numHeaders,
         int64_t seekPreRollUs)
-    : mSource(source),
+    : mBufferGroup(NULL),
+      mSource(source),
       mOffset(0),
       mCurGranulePosition(0),
       mPrevGranulePosition(0),
@@ -573,13 +578,13 @@
     return sizeof(header) + page->mNumSegments + totalSize;
 }
 
-media_status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) {
+media_status_t MyOpusExtractor::readNextPacket(MediaBufferHelperV3 **out) {
     if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) {
         // The first sample might not start at time 0; find out where by subtracting
         // the number of samples on the first page from the granule position
         // (position of last complete sample) of the first page. This happens
         // the first time before we attempt to read a packet from the first page.
-        MediaBufferBase *mBuf;
+        MediaBufferHelperV3 *mBuf;
         uint32_t numSamples = 0;
         uint64_t curGranulePosition = 0;
         while (true) {
@@ -617,24 +622,25 @@
     int32_t currentPageSamples;
     // Calculate timestamps by accumulating durations starting from the first sample of a page;
     // We assume that we only seek to page boundaries.
-    if ((*out)->meta_data().findInt32(kKeyValidSamples, &currentPageSamples)) {
+    AMediaFormat *meta = (*out)->meta_data();
+    if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, &currentPageSamples)) {
         // first packet in page
         if (mOffset == mFirstDataOffset) {
             currentPageSamples -= mStartGranulePosition;
-            (*out)->meta_data().setInt32(kKeyValidSamples, currentPageSamples);
+            AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, currentPageSamples);
         }
         mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
     }
 
     int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
-    (*out)->meta_data().setInt64(kKeyTime, timeUs);
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
 
     uint32_t frames = getNumSamplesInPacket(*out);
     mCurGranulePosition += frames;
     return AMEDIA_OK;
 }
 
-uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const {
+uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferHelperV3 *buffer) const {
     if (buffer == NULL || buffer->range_length() < 1) {
         return 0;
     }
@@ -680,10 +686,66 @@
     return numSamples;
 }
 
-media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) {
+/*
+ * basic mediabuffer implementation used during initial parsing of the
+ * header packets, which happens before we have a buffer group
+ */
+class StandAloneMediaBuffer : public MediaBufferHelperV3 {
+private:
+    void *mData;
+    size_t mSize;
+    size_t mOffset;
+    size_t mLength;
+    AMediaFormat *mFormat;
+public:
+    StandAloneMediaBuffer(size_t size) : MediaBufferHelperV3(NULL) {
+        mSize = size;
+        mData = malloc(mSize);
+        mOffset = 0;
+        mLength = mSize;
+        mFormat = AMediaFormat_new();
+        ALOGV("created standalone media buffer %p of size %zu", this, mSize);
+    }
+
+    ~StandAloneMediaBuffer() override {
+        free(mData);
+        AMediaFormat_delete(mFormat);
+        ALOGV("deleted standalone media buffer %p of size %zu", this, mSize);
+    }
+
+    void release() override {
+        delete this;
+    }
+
+    void* data() override {
+        return mData;
+    }
+
+    size_t size() override {
+        return mSize;
+    }
+
+    size_t range_offset() override {
+        return mOffset;
+    }
+
+    size_t range_length() override {
+        return mLength;
+    }
+
+    void set_range(size_t offset, size_t length) override {
+        mOffset = offset;
+        mLength = length;
+    }
+    AMediaFormat *meta_data() override {
+        return mFormat;
+    }
+};
+
+media_status_t MyOggExtractor::_readNextPacket(MediaBufferHelperV3 **out, bool calcVorbisTimestamp) {
     *out = NULL;
 
-    MediaBufferBase *buffer = NULL;
+    MediaBufferHelperV3 *buffer = NULL;
     int64_t timeUs = -1;
 
     for (;;) {
@@ -719,7 +781,13 @@
                 ALOGE("b/36592202");
                 return AMEDIA_ERROR_MALFORMED;
             }
-            MediaBufferBase *tmp = MediaBufferBase::Create(fullSize);
+            MediaBufferHelperV3 *tmp;
+            if (mBufferGroup) {
+                mBufferGroup->acquire_buffer(&tmp, false, fullSize);
+                ALOGV("acquired buffer %p from group", tmp);
+            } else {
+                tmp = new StandAloneMediaBuffer(fullSize);
+            }
             if (tmp == NULL) {
                 if (buffer != NULL) {
                     buffer->release();
@@ -727,6 +795,7 @@
                 ALOGE("b/36592202");
                 return AMEDIA_ERROR_MALFORMED;
             }
+            AMediaFormat_clear(tmp->meta_data());
             if (buffer != NULL) {
                 memcpy(tmp->data(), buffer->data(), buffer->range_length());
                 tmp->set_range(0, buffer->range_length());
@@ -756,8 +825,9 @@
                 // We've just read the entire packet.
 
                 if (mFirstPacketInPage) {
-                    buffer->meta_data().setInt32(
-                            kKeyValidSamples, mCurrentPageSamples);
+                    AMediaFormat *meta = buffer->meta_data();
+                    AMediaFormat_setInt32(
+                            meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
                     mFirstPacketInPage = false;
                 }
 
@@ -778,7 +848,8 @@
                         mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
                         mCurrentPage.mPrevPacketSize = curBlockSize;
                     }
-                    buffer->meta_data().setInt64(kKeyTime, timeUs);
+                    AMediaFormat *meta = buffer->meta_data();
+                    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
                 }
                 *out = buffer;
 
@@ -824,11 +895,13 @@
                 // is already complete.
 
                 if (timeUs >= 0) {
-                    buffer->meta_data().setInt64(kKeyTime, timeUs);
+                    AMediaFormat *meta = buffer->meta_data();
+                    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
                 }
 
-                buffer->meta_data().setInt32(
-                        kKeyValidSamples, mCurrentPageSamples);
+                AMediaFormat *meta = buffer->meta_data();
+                AMediaFormat_setInt32(
+                        meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
                 mFirstPacketInPage = false;
 
                 *out = buffer;
@@ -843,7 +916,7 @@
     AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);
 
     media_status_t err;
-    MediaBufferBase *packet;
+    MediaBufferHelperV3 *packet;
     for (size_t i = 0; i < mNumHeaders; ++i) {
         // ignore timestamp for configuration packets
         if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
@@ -920,7 +993,7 @@
     }
 }
 
-int32_t MyOggExtractor::getPacketBlockSize(MediaBufferBase *buffer) {
+int32_t MyOggExtractor::getPacketBlockSize(MediaBufferHelperV3 *buffer) {
     const uint8_t *data =
         (const uint8_t *)buffer->data() + buffer->range_offset();
 
@@ -960,7 +1033,7 @@
     return pcmSamplePosition * 1000000ll / kOpusSampleRate;
 }
 
-media_status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) {
+media_status_t MyOpusExtractor::verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type) {
     switch (type) {
         // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
         // header and comments such that we can share code with MyVorbisExtractor.
@@ -973,7 +1046,7 @@
     }
 }
 
-media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) {
+media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferHelperV3 *buffer) {
     const size_t kOpusHeaderSize = 19;
     const uint8_t *data =
         (const uint8_t *)buffer->data() + buffer->range_offset();
@@ -1001,7 +1074,7 @@
     return AMEDIA_OK;
 }
 
-media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
+media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferHelperV3 *buffer) {
     // add artificial framing bit so we can reuse _vorbis_unpack_comment
     int32_t commentSize = buffer->range_length() + 1;
     auto tmp = heapbuffer<uint8_t>(commentSize);
@@ -1094,7 +1167,7 @@
 }
 
 media_status_t MyVorbisExtractor::verifyHeader(
-        MediaBufferBase *buffer, uint8_t type) {
+        MediaBufferHelperV3 *buffer, uint8_t type) {
     const uint8_t *data =
         (const uint8_t *)buffer->data() + buffer->range_offset();
 
@@ -1262,7 +1335,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-MediaTrackHelperV2 *OggExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *OggExtractor::getTrack(size_t index) {
     if (index >= 1) {
         return NULL;
     }
@@ -1284,13 +1357,13 @@
     return mImpl->getFileMetaData(meta);
 }
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *) {
-    return wrapV2(new OggExtractor(new DataSourceHelper(source)));
+    return wrapV3(new OggExtractor(new DataSourceHelper(source)));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source,
         float *confidence,
         void **,
@@ -1311,11 +1384,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
         1, // version
         "Ogg Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index cd674f3..97506ad 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -31,11 +31,11 @@
 struct MyOggExtractor;
 struct OggSource;
 
-struct OggExtractor : public MediaExtractorPluginHelperV2 {
+struct OggExtractor : public MediaExtractorPluginHelperV3 {
     explicit OggExtractor(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/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 4a0e6da..58ef7b1 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -258,7 +258,7 @@
         callbackResult = maybeCallDataCallback(mCallbackBuffer, mCallbackFrames);
 
         if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
-            ALOGD("callback returned AAUDIO_CALLBACK_RESULT_STOP");
+            ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
             break;
         }
     }
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 2ae37a5..9af47b2 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -293,7 +293,7 @@
                 break;
             }
         } else if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
-            ALOGV("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
+            ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__);
             break;
         }
     }
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 319467e..cb243a0 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -184,3 +184,15 @@
         "libutils",
     ],
 }
+
+cc_test {
+    name: "test_return_stop",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_return_stop.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
diff --git a/media/libaaudio/tests/test_return_stop.cpp b/media/libaaudio/tests/test_return_stop.cpp
new file mode 100644
index 0000000..9a9e00c
--- /dev/null
+++ b/media/libaaudio/tests/test_return_stop.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+/**
+ * Return stop from the callback.
+ * Expect the callback to cease.
+ * Check the logcat for bad behavior.
+ */
+
+#include <stdio.h>
+#include <thread>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+
+#define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
+#define STOP_AT_MSEC          1000
+#define LOOP_DURATION_MSEC    4000
+#define SLEEP_DURATION_MSEC    200
+
+static void s_myErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error);
+
+struct AudioEngine {
+    AAudioStreamBuilder *builder = nullptr;
+    AAudioStream        *stream = nullptr;
+    std::thread         *thread = nullptr;
+    int32_t              stopAtFrame = 0;
+    bool                 stopped = false;
+    // These counters are read and written by the callback and the main thread.
+    std::atomic<int32_t> framesRead{};
+    std::atomic<int32_t> startingFramesRead{};
+    std::atomic<int32_t> framesCalled{};
+    std::atomic<int32_t> callbackCount{};
+    std::atomic<int32_t> callbackCountAfterStop{};
+
+    void reset() {
+        framesRead.store(0);
+        startingFramesRead.store(0);
+        framesCalled.store(0);
+        callbackCount.store(0);
+        callbackCountAfterStop.store(0);
+        stopped = false;
+    }
+};
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t s_myDataCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames
+) {
+    (void) audioData;
+    (void) numFrames;
+    AudioEngine *engine = (struct AudioEngine *)userData;
+    engine->callbackCount++;
+    if (engine->stopped) {
+        engine->callbackCountAfterStop++;
+    }
+
+    engine->framesRead = (int32_t)AAudioStream_getFramesRead(stream);
+    if (engine->startingFramesRead == 0) {
+        engine->startingFramesRead.store(engine->framesRead.load());
+    }
+    engine->framesCalled += numFrames;
+    if (engine->framesCalled >= engine->stopAtFrame) {
+        engine->stopped = true;
+        return AAUDIO_CALLBACK_RESULT_STOP;
+    } else {
+        return AAUDIO_CALLBACK_RESULT_CONTINUE;
+    }
+}
+
+static aaudio_result_t s_OpenAudioStream(struct AudioEngine *engine,
+                                         aaudio_direction_t direction,
+                                         aaudio_sharing_mode_t sharingMode,
+                                         aaudio_performance_mode_t perfMode) {
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    aaudio_result_t result = AAudio_createStreamBuilder(&engine->builder);
+    if (result != AAUDIO_OK) {
+        printf("AAudio_createStreamBuilder returned %s",
+               AAudio_convertResultToText(result));
+        return result;
+    }
+
+    // Request stream properties.
+    AAudioStreamBuilder_setFormat(engine->builder, AAUDIO_FORMAT_PCM_FLOAT);
+    AAudioStreamBuilder_setPerformanceMode(engine->builder, perfMode);
+    AAudioStreamBuilder_setSharingMode(engine->builder, sharingMode);
+    AAudioStreamBuilder_setDirection(engine->builder, direction);
+    AAudioStreamBuilder_setDataCallback(engine->builder, s_myDataCallbackProc, engine);
+    AAudioStreamBuilder_setErrorCallback(engine->builder, s_myErrorCallbackProc, engine);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(engine->builder, &engine->stream);
+    if (result != AAUDIO_OK) {
+        printf("AAudioStreamBuilder_openStream returned %s",
+               AAudio_convertResultToText(result));
+        return result;
+    }
+
+    return result;
+}
+
+static aaudio_result_t s_CloseAudioStream(struct AudioEngine *engine) {
+    aaudio_result_t result = AAUDIO_OK;
+    if (engine->stream != nullptr) {
+        result = AAudioStream_close(engine->stream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_close returned %s\n",
+                   AAudio_convertResultToText(result));
+        }
+        engine->stream = nullptr;
+    }
+    AAudioStreamBuilder_delete(engine->builder);
+    engine->builder = nullptr;
+    return result;
+}
+
+static void s_myErrorCallbackProc(
+        AAudioStream *stream __unused,
+        void *userData __unused,
+        aaudio_result_t error) {
+    printf("%s() - error = %d\n", __func__, error);
+}
+
+void usage() {
+    printf("test_return_stop [-i] [-x] [-n] [-c]\n");
+    printf("     -i direction INPUT, otherwise OUTPUT\n");
+    printf("     -x sharing mode EXCLUSIVE, otherwise SHARED\n");
+    printf("     -n performance mode NONE, otherwise LOW_LATENCY\n");
+    printf("     -c always return CONTINUE from callback, not STOP\n");
+}
+
+int main(int argc, char **argv) {
+    (void) argc;
+    (void) argv;
+    struct AudioEngine engine;
+    aaudio_sharing_mode_t sharingMode = AAUDIO_SHARING_MODE_SHARED;
+    aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
+    aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT;
+    aaudio_result_t result = AAUDIO_OK;
+    bool alwaysContinue = false;
+    int errorCount = 0;
+    int callbackResult = EXIT_SUCCESS;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("Test Return Stop V1.0\n");
+    printf("Wait for a few seconds.\n");
+    printf("You should see callbackCount and framesRead stop advancing\n");
+    printf("when callbackCount reaches %d msec\n", STOP_AT_MSEC);
+    printf("\n");
+
+    for (int i = 1; i < argc; i++) {
+        const char *arg = argv[i];
+        if (arg[0] == '-') {
+            char option = arg[1];
+            switch (option) {
+                case 'c':
+                    alwaysContinue = true;
+                    break;
+                case 'i':
+                    direction = AAUDIO_DIRECTION_INPUT;
+                    break;
+                case 'n':
+                    perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
+                    break;
+                case 'x':
+                    sharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+                    break;
+                default:
+                    usage();
+                    exit(EXIT_FAILURE);
+                    break;
+            }
+        } else {
+            usage();
+            exit(EXIT_FAILURE);
+            break;
+        }
+    }
+
+    result = s_OpenAudioStream(&engine, direction, sharingMode, perfMode);
+    if (result != AAUDIO_OK) {
+        printf("s_OpenAudioStream returned %s",
+               AAudio_convertResultToText(result));
+        errorCount++;
+    }
+
+    int32_t framesPerBurst = AAudioStream_getFramesPerBurst(engine.stream);
+    // Check to see what kind of stream we actually got.
+    int32_t deviceId = AAudioStream_getDeviceId(engine.stream);
+    aaudio_performance_mode_t actualPerfMode = AAudioStream_getPerformanceMode(engine.stream);
+    printf("-------- opened: deviceId = %3d, framesPerBurst = %3d, perfMode = %d\n",
+           deviceId, framesPerBurst, actualPerfMode);
+
+    // Calculate how many callbacks needed.
+    if (alwaysContinue) {
+        engine.stopAtFrame = INT32_MAX;
+    } else {
+        int32_t sampleRate = AAudioStream_getSampleRate(engine.stream);
+        engine.stopAtFrame = STOP_AT_MSEC * sampleRate / 1000;
+    }
+
+    for (int loops = 0; loops < 2 && result == AAUDIO_OK; loops++) {
+        engine.reset();
+
+        // Start stream.
+        result = AAudioStream_requestStart(engine.stream);
+        printf("AAudioStream_requestStart() returned %d >>>>>>>>>>>>>>>>>>>>>>\n", result);
+        if (result != AAUDIO_OK) {
+            errorCount++;
+            break;
+        }
+
+        if (result == AAUDIO_OK) {
+            const int watchLoops = LOOP_DURATION_MSEC / SLEEP_DURATION_MSEC;
+            for (int i = watchLoops; i > 0; i--) {
+                printf("playing silence #%02d, framesRead = %7d, framesWritten = %7d,"
+                       " framesCalled = %6d, callbackCount = %4d\n",
+                       i,
+                       (int32_t) AAudioStream_getFramesRead(engine.stream),
+                       (int32_t) AAudioStream_getFramesWritten(engine.stream),
+                       engine.framesCalled.load(),
+                       engine.callbackCount.load()
+                );
+                usleep(SLEEP_DURATION_MSEC * 1000);
+            }
+        }
+
+        if (engine.stopAtFrame != INT32_MAX) {
+            callbackResult = (engine.callbackCountAfterStop == 0) ? EXIT_SUCCESS
+                                                                             : EXIT_FAILURE;
+            if (callbackResult) {
+                printf("ERROR - Callback count after STOP = %d\n",
+                       engine.callbackCountAfterStop.load());
+                errorCount++;
+            }
+        }
+
+        if (engine.startingFramesRead.load() == engine.framesRead.load()) {
+            printf("ERROR - framesRead did not advance across callbacks\n");
+            errorCount++;
+        }
+
+        result = AAudioStream_requestStop(engine.stream);
+        printf("AAudioStream_requestStop() returned %d <<<<<<<<<<<<<<<<<<<<<\n", result);
+        if (result != AAUDIO_OK) {
+            errorCount++;
+        }
+        usleep(SLEEP_DURATION_MSEC * 1000);
+        printf("getFramesRead() = %d, getFramesWritten() = %d\n",
+               (int32_t) AAudioStream_getFramesRead(engine.stream),
+               (int32_t) AAudioStream_getFramesWritten(engine.stream));
+    }
+
+    s_CloseAudioStream(&engine);
+
+    printf("aaudio result = %d = %s\n", result, AAudio_convertResultToText(result));
+    printf("test %s\n", errorCount ? "FAILED" : "PASSED");
+
+    return errorCount ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index e21c235..bd3ef61 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -25,13 +25,13 @@
 // static
 sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
     if (hardware::audio::effect::V5_0::IEffectsFactory::getService() != nullptr) {
-        return V5_0::createEffectsFactoryHal();
+        return effect::V5_0::createEffectsFactoryHal();
     }
     if (hardware::audio::effect::V4_0::IEffectsFactory::getService() != nullptr) {
-        return V4_0::createEffectsFactoryHal();
+        return effect::V4_0::createEffectsFactoryHal();
     }
     if (hardware::audio::effect::V2_0::IEffectsFactory::getService() != nullptr) {
-        return V2_0::createEffectsFactoryHal();
+        return effect::V2_0::createEffectsFactoryHal();
     }
     return nullptr;
 }
diff --git a/media/libaudiohal/HalDeathHandlerHidl.cpp b/media/libaudiohal/HalDeathHandlerHidl.cpp
index 1e3ab58..6e33523 100644
--- a/media/libaudiohal/HalDeathHandlerHidl.cpp
+++ b/media/libaudiohal/HalDeathHandlerHidl.cpp
@@ -54,7 +54,7 @@
         handler.second();
     }
     ALOGE("HAL server crashed, audio server is restarting");
-    exit(1);
+    _exit(1);  // Avoid calling atexit handlers, as this code runs on a thread from RPC threadpool.
 }
 
 } // namespace android
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index 9747859..9f8a520 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -22,19 +22,12 @@
 
 #include "ConversionHelperHidl.h"
 
-using ::android::hardware::audio::CPP_VERSION::Result;
-
-#if MAJOR_VERSION >= 4
-using ::android::hardware::audio::CPP_VERSION::AudioMicrophoneChannelMapping;
-using ::android::hardware::audio::CPP_VERSION::AudioMicrophoneDirectionality;
-using ::android::hardware::audio::CPP_VERSION::AudioMicrophoneLocation;
-using ::android::hardware::audio::CPP_VERSION::DeviceAddress;
-using ::android::hardware::audio::CPP_VERSION::MicrophoneInfo;
-#endif
-
 namespace android {
 namespace CPP_VERSION {
 
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+
 // static
 status_t ConversionHelperHidl::keysFromHal(const String8& keys, hidl_vec<hidl_string> *hidlKeys) {
     AudioParameter halKeys(keys);
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.cpp b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
index 6ef4e8a..5367972 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
@@ -30,6 +30,7 @@
 using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 // static
@@ -142,5 +143,6 @@
     memcpy(mExternalData, mAudioBuffer.raw, size);
 }
 
+} // namespace effect
 } // namespace CPP_VERSION
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.h b/media/libaudiohal/impl/EffectBufferHalHidl.h
index 0c99a02..4826813 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.h
@@ -23,13 +23,15 @@
 #include <media/audiohal/EffectBufferHalInterface.h>
 #include <system/audio_effect.h>
 
-using android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
 using android::hardware::hidl_memory;
 using android::hidl::memory::V1_0::IMemory;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
 class EffectBufferHalHidl : public EffectBufferHalInterface
 {
   public:
@@ -73,6 +75,7 @@
 };
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index df79b95..b0597b3 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -26,11 +26,6 @@
 #include "EffectHalHidl.h"
 #include "HidlUtils.h"
 
-using ::android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferAccess;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfigParameters;
-using ::android::hardware::audio::effect::CPP_VERSION::MessageQueueFlagBits;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
 using ::android::hardware::audio::common::utils::EnumBitfield;
 using ::android::hardware::hidl_vec;
@@ -38,9 +33,11 @@
 using ::android::hardware::Return;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
         : mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
@@ -338,4 +335,5 @@
 }
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index cd447ff..9d9f707 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -23,17 +23,15 @@
 #include <fmq/MessageQueue.h>
 #include <system/audio_effect.h>
 
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using EffectResult = ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::EventFlag;
 using ::android::hardware::MessageQueue;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
 class EffectHalHidl : public EffectHalInterface
 {
   public:
@@ -70,7 +68,7 @@
 
   private:
     friend class EffectsFactoryHalHidl;
-    typedef MessageQueue<EffectResult, hardware::kSynchronizedReadWrite> StatusMQ;
+    typedef MessageQueue<Result, hardware::kSynchronizedReadWrite> StatusMQ;
 
     sp<IEffect> mEffect;
     const uint64_t mEffectId;
@@ -80,7 +78,7 @@
     std::unique_ptr<StatusMQ> mStatusMQ;
     EventFlag* mEfGroup;
 
-    static status_t analyzeResult(const EffectResult& result);
+    static status_t analyzeResult(const Result& result);
     static void effectBufferConfigFromHal(
             const buffer_config_t& halConfig, EffectBufferConfig* config);
     static void effectBufferConfigToHal(
@@ -105,6 +103,7 @@
 };
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECT_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 7fea466..7fd6bde 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -26,14 +26,14 @@
 #include "HidlUtils.h"
 
 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
 using ::android::hardware::Return;
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
     mEffectsFactory = IEffectsFactory::getService();
@@ -145,6 +145,6 @@
     return EffectBufferHalHidl::mirror(external, size, buffer);
 }
 
-
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7027153..01178ff 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -24,11 +24,12 @@
 #include "ConversionHelperHidl.h"
 
 namespace android {
+namespace effect {
 namespace CPP_VERSION {
 
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffectsFactory;
 using ::android::hardware::hidl_vec;
+using ::android::CPP_VERSION::ConversionHelperHidl;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public ConversionHelperHidl
 {
@@ -70,6 +71,7 @@
 }
 
 } // namespace CPP_VERSION
+} // namespace effect
 } // namespace android
 
 #endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 9765f1e..c12b362 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -35,6 +35,7 @@
 namespace android {
 namespace CPP_VERSION {
 
+using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
 using ReadCommand = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadCommand;
 
 using namespace ::android::hardware::audio::common::CPP_VERSION;
diff --git a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
index 1d912a0..c7319d0 100644
--- a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
@@ -25,18 +25,29 @@
 
 namespace android {
 
+namespace effect {
 namespace V2_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V2_0
 
 namespace V4_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V4_0
 
 namespace V5_0 {
 sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
+} // namespace V5_0
+} // namespace effect
+
+namespace V2_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V2_0
+
+namespace V4_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V4_0
+
+namespace V5_0 {
 sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
 } // namespace V5_0
 
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
new file mode 100644
index 0000000..817fb0b
--- /dev/null
+++ b/media/libaudioprocessing/Android.bp
@@ -0,0 +1,54 @@
+cc_defaults {
+    name: "libaudioprocessing_defaults",
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libaudiohal",
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+        "libnbaio",
+        "libnblog",
+        "libsonic",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+
+        // uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
+        // "-DUSE_NEON=false",
+    ],
+}
+
+cc_library_shared {
+    name: "libaudioprocessing",
+    defaults: ["libaudioprocessing_defaults"],
+
+    srcs: [
+        "BufferProviders.cpp",
+        "RecordBufferConverter.cpp",
+    ],
+    whole_static_libs: ["libaudioprocessing_arm"],
+}
+
+cc_library_static {
+    name: "libaudioprocessing_arm",
+    defaults: ["libaudioprocessing_defaults"],
+
+    srcs: [
+        "AudioMixer.cpp",
+        "AudioResampler.cpp",
+        "AudioResamplerCubic.cpp",
+        "AudioResamplerSinc.cpp",
+        "AudioResamplerDyn.cpp",
+    ],
+
+    arch: {
+        arm: {
+            instruction_set: "arm",
+        },
+    },
+}
diff --git a/media/libaudioprocessing/Android.mk b/media/libaudioprocessing/Android.mk
deleted file mode 100644
index da1ecc2..0000000
--- a/media/libaudioprocessing/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    AudioMixer.cpp.arm \
-    AudioResampler.cpp.arm \
-    AudioResamplerCubic.cpp.arm \
-    AudioResamplerSinc.cpp.arm \
-    AudioResamplerDyn.cpp.arm \
-    BufferProviders.cpp \
-    RecordBufferConverter.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(TOP) \
-    $(call include-path-for, audio-utils) \
-    $(LOCAL_PATH)/include \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libaudiohal \
-    libaudioutils \
-    libcutils \
-    liblog \
-    libnbaio \
-    libnblog \
-    libsonic \
-    libutils \
-
-LOCAL_MODULE := libaudioprocessing
-
-LOCAL_CFLAGS := -Werror -Wall
-
-# uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
-#LOCAL_CFLAGS += -DUSE_NEON=false
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index a1a1a0d..b764ccb 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -17,10 +17,12 @@
 #define LOG_TAG "BufferProvider"
 //#define LOG_NDEBUG 0
 
+#include <algorithm>
+
 #include <audio_utils/primitives.h>
 #include <audio_utils/format.h>
 #include <audio_utils/channels.h>
-#include <external/sonic/sonic.h>
+#include <sonic.h>
 #include <media/audiohal/EffectBufferHalInterface.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -36,13 +38,6 @@
 namespace android {
 
 // ----------------------------------------------------------------------------
-
-template <typename T>
-static inline T min(const T& a, const T& b)
-{
-    return a < b ? a : b;
-}
-
 CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
         size_t outputFrameSize, size_t bufferFrameCount) :
         mInputFrameSize(inputFrameSize),
@@ -100,8 +95,8 @@
         mConsumed = 0;
     }
     ALOG_ASSERT(mConsumed < mBuffer.frameCount);
-    size_t count = min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
-    count = min(count, pBuffer->frameCount);
+    size_t count = std::min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
+    count = std::min(count, pBuffer->frameCount);
     pBuffer->raw = mLocalBufferData;
     pBuffer->frameCount = count;
     copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
@@ -491,7 +486,7 @@
         }
 
         // time-stretch the data
-        dstAvailable = min(mLocalBufferFrameCount - mRemaining, outputDesired);
+        dstAvailable = std::min(mLocalBufferFrameCount - mRemaining, outputDesired);
         size_t srcAvailable = mBuffer.frameCount;
         processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
                 mBuffer.raw, &srcAvailable);
@@ -589,7 +584,7 @@
                   } else {
                       // cyclically repeat the source.
                       for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
-                          size_t remaining = min(*srcFrames, *dstFrames - count);
+                          size_t remaining = std::min(*srcFrames, *dstFrames - count);
                           memcpy((uint8_t*)dstBuffer + mFrameSize * count,
                                   srcBuffer, mFrameSize * remaining);
                       }
@@ -657,9 +652,9 @@
         audio_format_t format, size_t inChannelCount, size_t outChannelCount,
         audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
         CopyBufferProvider(
-                audio_bytes_per_frame(inChannelCount, format),
-                audio_bytes_per_frame(outChannelCount, format),
-                0 /*bufferFrameCount*/),
+                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
+                audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
+                contractedFrameCount),
         mFormat(format),
         mInChannelCount(inChannelCount),
         mOutChannelCount(outChannelCount),
diff --git a/media/libaudioprocessing/audio-resampler/Android.bp b/media/libaudioprocessing/audio-resampler/Android.bp
new file mode 100644
index 0000000..dc70310
--- /dev/null
+++ b/media/libaudioprocessing/audio-resampler/Android.bp
@@ -0,0 +1,15 @@
+cc_library_shared {
+    name: "libaudio-resampler",
+
+    srcs: ["AudioResamplerCoefficients.cpp"],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
diff --git a/media/libaudioprocessing/audio-resampler/Android.mk b/media/libaudioprocessing/audio-resampler/Android.mk
deleted file mode 100644
index bb2807c..0000000
--- a/media/libaudioprocessing/audio-resampler/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    AudioResamplerCoefficients.cpp
-
-LOCAL_MODULE := libaudio-resampler
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES  := libutils liblog
-
-LOCAL_CFLAGS += -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libaudioprocessing/tests/Android.bp b/media/libaudioprocessing/tests/Android.bp
new file mode 100644
index 0000000..811c16b
--- /dev/null
+++ b/media/libaudioprocessing/tests/Android.bp
@@ -0,0 +1,51 @@
+// Build the unit tests for libaudioprocessing
+
+cc_defaults {
+    name: "libaudioprocessing_test_defaults",
+
+    header_libs: ["libbase_headers"],
+    shared_libs: [
+        "libaudioutils",
+        "libaudioprocessing",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
+
+//
+// resampler unit test
+//
+cc_test {
+    name: "resampler_tests",
+    defaults: ["libaudioprocessing_test_defaults"],
+
+    srcs: ["resampler_tests.cpp"],
+}
+
+//
+// audio mixer test tool
+//
+cc_binary {
+    name: "test-mixer",
+    defaults: ["libaudioprocessing_test_defaults"],
+
+    srcs: ["test-mixer.cpp"],
+    static_libs: ["libsndfile"],
+}
+
+//
+// build audio resampler test tool
+//
+cc_binary {
+    name: "test-resampler",
+    defaults: ["libaudioprocessing_test_defaults"],
+
+    srcs: ["test-resampler.cpp"],
+    static_libs: ["libsndfile"],
+}
diff --git a/media/libaudioprocessing/tests/Android.mk b/media/libaudioprocessing/tests/Android.mk
deleted file mode 100644
index 31ffbdc..0000000
--- a/media/libaudioprocessing/tests/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-# Build the unit tests for libaudioprocessing
-
-LOCAL_PATH := $(call my-dir)
-
-#
-# resampler unit test
-#
-include $(CLEAR_VARS)
-
-LOCAL_SHARED_LIBRARIES := \
-    libaudioutils \
-    libaudioprocessing \
-    libcutils \
-    liblog \
-    libutils \
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-
-LOCAL_SRC_FILES := \
-    resampler_tests.cpp
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := resampler_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_NATIVE_TEST)
-
-#
-# audio mixer test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    test-mixer.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-
-LOCAL_STATIC_LIBRARIES := \
-    libsndfile \
-
-LOCAL_SHARED_LIBRARIES := \
-    libaudioprocessing \
-    libaudioutils \
-    libcutils \
-    liblog \
-    libutils \
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := test-mixer
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
-
-#
-# build audio resampler test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    test-resampler.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-
-LOCAL_STATIC_LIBRARIES := \
-    libsndfile \
-
-LOCAL_SHARED_LIBRARIES := \
-    libaudioprocessing \
-    libaudioutils \
-    libcutils \
-    liblog \
-    libutils \
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := test-resampler
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 351b1ee..76b4adc 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -305,7 +305,7 @@
         return parseWithPath(path);
     }
 
-    for (std::string location : DEFAULT_LOCATIONS) {
+    for (const std::string& location : DEFAULT_LOCATIONS) {
         std::string defaultPath = location + '/' + DEFAULT_NAME;
         if (access(defaultPath.c_str(), R_OK) != 0) {
             continue;
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
index a1fa79a..cc066b0 100644
--- a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -199,8 +199,10 @@
 #define LVDBE_CAP_FS_44100               128
 #define LVDBE_CAP_FS_48000               256
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-#define LVDBE_CAP_FS_96000               512
-#define LVDBE_CAP_FS_192000              1024
+#define LVDBE_CAP_FS_88200               512
+#define LVDBE_CAP_FS_96000               1024
+#define LVDBE_CAP_FS_176400              2048
+#define LVDBE_CAP_FS_192000              4096
 #endif
 
 typedef enum
@@ -215,8 +217,10 @@
     LVDBE_FS_44100 = 7,
     LVDBE_FS_48000 = 8,
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-    LVDBE_FS_96000 = 9,
-    LVDBE_FS_192000 = 10,
+    LVDBE_FS_88200 = 9,
+    LVDBE_FS_96000 = 10,
+    LVDBE_FS_176400 = 11,
+    LVDBE_FS_192000 = 12,
 #endif
     LVDBE_FS_MAX   = LVM_MAXINT_32
 } LVDBE_Fs_en;
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
index 4ecaf14..8f058e8 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
@@ -580,12 +580,24 @@
 #define HPF_Fs48000_Fc55_B2                       0.989882f
 
 #ifdef HIGHER_FS
+#define HPF_Fs88200_Fc55_A0                       0.985818f
+#define HPF_Fs88200_Fc55_A1                       (-1.971636f)
+#define HPF_Fs88200_Fc55_A2                       0.985818f
+#define HPF_Fs88200_Fc55_B1                       (-1.994466f)
+#define HPF_Fs88200_Fc55_B2                       0.994481f
+
 #define HPF_Fs96000_Fc55_A0                       0.986040f
 #define HPF_Fs96000_Fc55_A1                       (-1.972080f)
 #define HPF_Fs96000_Fc55_A2                       0.986040f
 #define HPF_Fs96000_Fc55_B1                       (-1.994915f)
 #define HPF_Fs96000_Fc55_B2                       0.994928f
 
+#define HPF_Fs176400_Fc55_A0                      0.987183f
+#define HPF_Fs176400_Fc55_A1                      (-1.974366f)
+#define HPF_Fs176400_Fc55_A2                      0.987183f
+#define HPF_Fs176400_Fc55_B1                      (-1.997233f)
+#define HPF_Fs176400_Fc55_B2                      0.997237f
+
 #define HPF_Fs192000_Fc55_A0                      0.987294f
 #define HPF_Fs192000_Fc55_A1                      (-1.974588f)
 #define HPF_Fs192000_Fc55_A2                      0.987294f
@@ -642,12 +654,24 @@
 #define HPF_Fs48000_Fc66_B2                       0.987871f
 
 #ifdef HIGHER_FS
+#define HPF_Fs88200_Fc66_A0                       0.985273f
+#define HPF_Fs88200_Fc66_A1                       (-1.970546f)
+#define HPF_Fs88200_Fc66_A2                       0.985273f
+#define HPF_Fs88200_Fc66_B1                       (-1.993359f)
+#define HPF_Fs88200_Fc66_B2                       0.993381f
+
 #define HPF_Fs96000_Fc66_A0                       0.985539f
 #define HPF_Fs96000_Fc66_A1                       (-1.971077f)
 #define HPF_Fs96000_Fc66_A2                       0.985539f
 #define HPF_Fs96000_Fc66_B1                       (-1.993898f)
 #define HPF_Fs96000_Fc66_B2                       0.993917f
 
+#define HPF_Fs176400_Fc66_A0                      0.986910f
+#define HPF_Fs176400_Fc66_A1                      (-1.973820f)
+#define HPF_Fs176400_Fc66_A2                      0.986910f
+#define HPF_Fs176400_Fc66_B1                      (-1.996679f)
+#define HPF_Fs176400_Fc66_B2                      0.996685f
+
 #define HPF_Fs192000_Fc66_A0                      0.987043f
 #define HPF_Fs192000_Fc66_A1                      (-1.974086f)
 #define HPF_Fs192000_Fc66_A2                      0.987043f
@@ -703,12 +727,24 @@
 #define HPF_Fs48000_Fc78_B2                       0.985681f
 
 #ifdef HIGHER_FS
+#define HPF_Fs88200_Fc78_A0                       0.984678f
+#define HPF_Fs88200_Fc78_A1                       (-1.969356f)
+#define HPF_Fs88200_Fc78_A2                       0.984678f
+#define HPF_Fs88200_Fc78_B1                       (-1.992151f)
+#define HPF_Fs88200_Fc78_B2                       0.992182f
+
 #define HPF_Fs96000_Fc78_A0                       0.984992f
 #define HPF_Fs96000_Fc78_A1                       (-1.969984f)
 #define HPF_Fs96000_Fc78_A2                       0.984992f
 #define HPF_Fs96000_Fc78_B1                       (-1.992789f)
 #define HPF_Fs96000_Fc78_B2                       0.992815f
 
+#define HPF_Fs176400_Fc78_A0                      0.986612f
+#define HPF_Fs176400_Fc78_A1                      (-1.973224f)
+#define HPF_Fs176400_Fc78_A2                      0.986612f
+#define HPF_Fs176400_Fc78_B1                      (-1.996076f)
+#define HPF_Fs176400_Fc78_B2                      0.996083f
+
 #define HPF_Fs192000_Fc78_A0                      0.986769f
 #define HPF_Fs192000_Fc78_A1                      (-1.973539f)
 #define HPF_Fs192000_Fc78_A2                      0.986769f
@@ -764,12 +800,24 @@
 #define HPF_Fs48000_Fc90_B2                      0.983497f
 
 #ifdef HIGHER_FS
+#define HPF_Fs88200_Fc90_A0                       0.984084f
+#define HPF_Fs88200_Fc90_A1                       (-1.968168f)
+#define HPF_Fs88200_Fc90_A2                       0.984084f
+#define HPF_Fs88200_Fc90_B1                       (-1.990944f)
+#define HPF_Fs88200_Fc90_B2                       0.990985f
+
 #define HPF_Fs96000_Fc90_A0                       0.984446f
 #define HPF_Fs96000_Fc90_A1                       (-1.968892f)
 #define HPF_Fs96000_Fc90_A2                       0.984446f
 #define HPF_Fs96000_Fc90_B1                       (-1.991680f)
 #define HPF_Fs96000_Fc90_B2                       0.991714f
 
+#define HPF_Fs176400_Fc90_A0                      0.986314f
+#define HPF_Fs176400_Fc90_A1                      (-1.972629f)
+#define HPF_Fs176400_Fc90_A2                      0.986314f
+#define HPF_Fs176400_Fc90_B1                      (-1.995472f)
+#define HPF_Fs176400_Fc90_B2                      0.995482f
+
 #define HPF_Fs192000_Fc90_A0                      0.986496f
 #define HPF_Fs192000_Fc90_A1                      (-1.972992f)
 #define HPF_Fs192000_Fc90_A2                      0.986496f
@@ -831,12 +879,24 @@
 #define BPF_Fs48000_Fc55_B2                      0.996875f
 
 #ifdef HIGHER_FS
+#define BPF_Fs88200_Fc55_A0                      0.000831f
+#define BPF_Fs88200_Fc55_A1                      0.000000f
+#define BPF_Fs88200_Fc55_A2                      (-0.000831f)
+#define BPF_Fs88200_Fc55_B1                      (-1.998321f)
+#define BPF_Fs88200_Fc55_B2                      0.998338f
+
 #define BPF_Fs96000_Fc55_A0                      0.000762f
 #define BPF_Fs96000_Fc55_A1                      0.000000f
 #define BPF_Fs96000_Fc55_A2                      (-0.000762f)
 #define BPF_Fs96000_Fc55_B1                      (-1.998461f)
 #define BPF_Fs96000_Fc55_B2                      0.998477f
 
+#define BPF_Fs176400_Fc55_A0                     0.000416f
+#define BPF_Fs176400_Fc55_A1                     0.000000f
+#define BPF_Fs176400_Fc55_A2                     (-0.000416f)
+#define BPF_Fs176400_Fc55_B1                     (-1.999164f)
+#define BPF_Fs176400_Fc55_B2                     0.999169f
+
 #define BPF_Fs192000_Fc55_A0                     0.000381f
 #define BPF_Fs192000_Fc55_A1                     0.000000f
 #define BPF_Fs192000_Fc55_A2                     (-0.000381f)
@@ -892,12 +952,24 @@
 #define BPF_Fs48000_Fc66_B2                     0.995690f
 
 #ifdef HIGHER_FS
+#define BPF_Fs88200_Fc66_A0                     0.001146f
+#define BPF_Fs88200_Fc66_A1                     0.000000f
+#define BPF_Fs88200_Fc66_A2                     (-0.001146f)
+#define BPF_Fs88200_Fc66_B1                     (-1.997684f)
+#define BPF_Fs88200_Fc66_B2                     0.997708f
+
 #define BPF_Fs96000_Fc66_A0                     0.001055f
 #define BPF_Fs96000_Fc66_A1                     0.000000f
 #define BPF_Fs96000_Fc66_A2                     (-0.001055f)
 #define BPF_Fs96000_Fc66_B1                     (-1.997868f)
 #define BPF_Fs96000_Fc66_B2                     0.997891f
 
+#define BPF_Fs176400_Fc66_A0                    0.000573f
+#define BPF_Fs176400_Fc66_A1                    0.000000f
+#define BPF_Fs176400_Fc66_A2                    (-0.000573f)
+#define BPF_Fs176400_Fc66_B1                    (-1.998847f)
+#define BPF_Fs176400_Fc66_B2                    0.998853f
+
 #define BPF_Fs192000_Fc66_A0                    0.000528f
 #define BPF_Fs192000_Fc66_A1                    0.000000f
 #define BPF_Fs192000_Fc66_A2                   (-0.000528f)
@@ -953,12 +1025,24 @@
 #define BPF_Fs48000_Fc78_B2                     0.993639f
 
 #ifdef HIGHER_FS
+#define BPF_Fs88200_Fc78_A0                    0.001693f
+#define BPF_Fs88200_Fc78_A1                    0.000000f
+#define BPF_Fs88200_Fc78_A2                    (-0.001693f)
+#define BPF_Fs88200_Fc78_B1                    (-1.996582f)
+#define BPF_Fs88200_Fc78_B2                    0.996615f
+
 #define BPF_Fs96000_Fc78_A0                     0.001555f
 #define BPF_Fs96000_Fc78_A1                     0.000000f
 #define BPF_Fs96000_Fc78_A2                    (-0.0015555f)
 #define BPF_Fs96000_Fc78_B1                    (-1.996860f)
 #define BPF_Fs96000_Fc78_B2                     0.996891f
 
+#define BPF_Fs176400_Fc78_A0                    0.000847f
+#define BPF_Fs176400_Fc78_A1                    0.000000f
+#define BPF_Fs176400_Fc78_A2                    (-0.000847f)
+#define BPF_Fs176400_Fc78_B1                    (-1.998298f)
+#define BPF_Fs176400_Fc78_B2                    0.998306f
+
 #define BPF_Fs192000_Fc78_A0                    0.000778f
 #define BPF_Fs192000_Fc78_A1                    0.000000f
 #define BPF_Fs192000_Fc78_A2                   (-0.000778f)
@@ -1014,12 +1098,24 @@
 #define BPF_Fs48000_Fc90_B2                      0.992177f
 
 #ifdef HIGHER_FS
+#define BPF_Fs88200_Fc90_A0                      0.002083f
+#define BPF_Fs88200_Fc90_A1                      0.000000f
+#define BPF_Fs88200_Fc90_A2                      (-0.002083f)
+#define BPF_Fs88200_Fc90_B1                      (-1.995791f)
+#define BPF_Fs88200_Fc90_B2                      0.995835f
+
 #define BPF_Fs96000_Fc90_A0                      0.001913f
 #define BPF_Fs96000_Fc90_A1                      0.000000f
 #define BPF_Fs96000_Fc90_A2                     (-0.001913f)
 #define BPF_Fs96000_Fc90_B1                     (-1.996134f)
 #define BPF_Fs96000_Fc90_B2                      0.996174f
 
+#define BPF_Fs176400_Fc90_A0                     0.001042f
+#define BPF_Fs176400_Fc90_A1                     0.000000f
+#define BPF_Fs176400_Fc90_A2                     (-0.001042f)
+#define BPF_Fs176400_Fc90_B1                     (-1.997904f)
+#define BPF_Fs176400_Fc90_B2                     0.997915f
+
 #define BPF_Fs192000_Fc90_A0                     0.000958f
 #define BPF_Fs192000_Fc90_A1                     0.000000f
 #define BPF_Fs192000_Fc90_A2                    (-0.000958f)
@@ -1045,7 +1141,9 @@
 #define AGC_ATTACK_Fs48000                            0.971628f
 
 #ifdef HIGHER_FS
+#define AGC_ATTACK_Fs88200                             0.984458f
 #define AGC_ATTACK_Fs96000                             0.985712f
+#define AGC_ATTACK_Fs176400                            0.992199f
 #define AGC_ATTACK_Fs192000                            0.992830f
 #endif
 
@@ -1062,7 +1160,9 @@
 #define AGC_DECAY_Fs48000                             0.000007f
 
 #ifdef HIGHER_FS
+#define AGC_DECAY_Fs88200                            0.0000038f
 #define AGC_DECAY_FS96000                            0.0000035f
+#define AGC_DECAY_Fs176400                          0.00000188f
 #define AGC_DECAY_FS192000                          0.00000175f
 #endif
 
@@ -1125,7 +1225,9 @@
 #define VOL_TC_Fs44100                                  0.004525f
 #define VOL_TC_Fs48000                                  0.004158f
 #ifdef HIGHER_FS
+#define VOL_TC_Fs88200                                  0.002263f
 #define VOL_TC_Fs96000                                  0.002079f
+#define VOL_TC_Fs176400                                 0.001131f
 #define VOL_TC_Fs192000                                 0.001039f
 #endif
 #define MIX_TC_Fs8000                                   29365         /* Floating point value 0.896151 */
@@ -1138,9 +1240,13 @@
 #define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
 #define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
 #ifdef HIGHER_FS
+/* Floating point value 0.989704 */
+#define MIX_TC_Fs88200                                  32430
 #define MIX_TC_Fs96000                                  32456         /* Floating point value 0.990530 */
+/* Floating point value 0.994838 */
+#define MIX_TC_Fs176400                                 32598
 #define MIX_TC_Fs192000                                 32611         /* Floating point value 0.992524 */
 #endif
 
 #endif /*BUILD_FLOAT*/
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
index c4a9b14..a2ce404 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
@@ -88,11 +88,21 @@
      -HPF_Fs48000_Fc55_B2,
      -HPF_Fs48000_Fc55_B1},
 #ifdef HIGHER_FS
+    {HPF_Fs88200_Fc55_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc55_A1,
+     HPF_Fs88200_Fc55_A0,
+     -HPF_Fs88200_Fc55_B2,
+     -HPF_Fs88200_Fc55_B1},
     {HPF_Fs96000_Fc55_A2,                /* 96kS/s coefficients */
      HPF_Fs96000_Fc55_A1,
      HPF_Fs96000_Fc55_A0,
      -HPF_Fs96000_Fc55_B2,
      -HPF_Fs96000_Fc55_B1},
+    {HPF_Fs176400_Fc55_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc55_A1,
+     HPF_Fs176400_Fc55_A0,
+     -HPF_Fs176400_Fc55_B2,
+     -HPF_Fs176400_Fc55_B1},
     {HPF_Fs192000_Fc55_A2,                /* 192kS/s coefficients */
      HPF_Fs192000_Fc55_A1,
      HPF_Fs192000_Fc55_A0,
@@ -147,11 +157,21 @@
      -HPF_Fs48000_Fc66_B2,
      -HPF_Fs48000_Fc66_B1},
 #ifdef HIGHER_FS
+    {HPF_Fs88200_Fc66_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc66_A1,
+     HPF_Fs88200_Fc66_A0,
+     -HPF_Fs88200_Fc66_B2,
+     -HPF_Fs88200_Fc66_B1},
     {HPF_Fs96000_Fc66_A2,                /* 96kS/s coefficients */
      HPF_Fs96000_Fc66_A1,
      HPF_Fs96000_Fc66_A0,
      -HPF_Fs96000_Fc66_B2,
      -HPF_Fs96000_Fc66_B1},
+    {HPF_Fs176400_Fc66_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc66_A1,
+     HPF_Fs176400_Fc66_A0,
+     -HPF_Fs176400_Fc66_B2,
+     -HPF_Fs176400_Fc66_B1},
     {HPF_Fs192000_Fc66_A2,                /* 192kS/s coefficients */
      HPF_Fs192000_Fc66_A1,
      HPF_Fs192000_Fc66_A0,
@@ -207,11 +227,21 @@
      -HPF_Fs48000_Fc78_B2,
      -HPF_Fs48000_Fc78_B1},
 #ifdef HIGHER_FS
+    {HPF_Fs88200_Fc78_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc78_A1,
+     HPF_Fs88200_Fc78_A0,
+     -HPF_Fs88200_Fc78_B2,
+     -HPF_Fs88200_Fc78_B1},
     {HPF_Fs96000_Fc78_A2,                /* 96kS/s coefficients */
      HPF_Fs96000_Fc78_A1,
      HPF_Fs96000_Fc78_A0,
      -HPF_Fs96000_Fc78_B2,
      -HPF_Fs96000_Fc78_B1},
+    {HPF_Fs176400_Fc78_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc78_A1,
+     HPF_Fs176400_Fc78_A0,
+     -HPF_Fs176400_Fc78_B2,
+     -HPF_Fs176400_Fc78_B1},
     {HPF_Fs192000_Fc78_A2,                /* 192kS/s coefficients */
      HPF_Fs192000_Fc78_A1,
      HPF_Fs192000_Fc78_A0,
@@ -269,11 +299,21 @@
 
 #ifdef HIGHER_FS
     ,
+    {HPF_Fs88200_Fc90_A2,                /* 88kS/s coefficients */
+     HPF_Fs88200_Fc90_A1,
+     HPF_Fs88200_Fc90_A0,
+     -HPF_Fs88200_Fc90_B2,
+     -HPF_Fs88200_Fc90_B1},
     {HPF_Fs96000_Fc90_A2,                /* 96kS/s coefficients */
      HPF_Fs96000_Fc90_A1,
      HPF_Fs96000_Fc90_A0,
      -HPF_Fs96000_Fc90_B2,
      -HPF_Fs96000_Fc90_B1},
+    {HPF_Fs176400_Fc90_A2,                /* 176kS/s coefficients */
+     HPF_Fs176400_Fc90_A1,
+     HPF_Fs176400_Fc90_A0,
+     -HPF_Fs176400_Fc90_B2,
+     -HPF_Fs176400_Fc90_B1},
     {HPF_Fs192000_Fc90_A2,                /* 192kS/s coefficients */
      HPF_Fs192000_Fc90_A1,
      HPF_Fs192000_Fc90_A0,
@@ -320,9 +360,15 @@
      -BPF_Fs48000_Fc55_B2,
      -BPF_Fs48000_Fc55_B1},
 #ifdef HIGHER_FS
+     {BPF_Fs88200_Fc55_A0,                /* 88kS/s coefficients */
+      -BPF_Fs88200_Fc55_B2,
+      -BPF_Fs88200_Fc55_B1},
      {BPF_Fs96000_Fc55_A0,                /* 96kS/s coefficients */
      -BPF_Fs96000_Fc55_B2,
      -BPF_Fs96000_Fc55_B1},
+     {BPF_Fs176400_Fc55_A0,                /* 176kS/s coefficients */
+      -BPF_Fs176400_Fc55_B2,
+      -BPF_Fs176400_Fc55_B1},
      {BPF_Fs192000_Fc55_A0,                /* 192kS/s coefficients */
      -BPF_Fs192000_Fc55_B2,
      -BPF_Fs192000_Fc55_B1},
@@ -357,9 +403,15 @@
      -BPF_Fs48000_Fc66_B2,
      -BPF_Fs48000_Fc66_B1},
 #ifdef HIGHER_FS
+    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc66_B2,
+     -BPF_Fs88200_Fc66_B1},
     {BPF_Fs96000_Fc66_A0,                /* 96kS/s coefficients */
      -BPF_Fs96000_Fc66_B2,
      -BPF_Fs96000_Fc66_B1},
+    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc66_B2,
+     -BPF_Fs176400_Fc66_B1},
     {BPF_Fs192000_Fc66_A0,                /* 192kS/s coefficients */
      -BPF_Fs192000_Fc66_B2,
      -BPF_Fs192000_Fc66_B1},
@@ -394,9 +446,15 @@
      -BPF_Fs48000_Fc78_B2,
      -BPF_Fs48000_Fc78_B1},
 #ifdef HIGHER_FS
+    {BPF_Fs88200_Fc66_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc66_B2,
+     -BPF_Fs88200_Fc66_B1},
     {BPF_Fs96000_Fc78_A0,                /* 96kS/s coefficients */
      -BPF_Fs96000_Fc78_B2,
      -BPF_Fs96000_Fc78_B1},
+    {BPF_Fs176400_Fc66_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc66_B2,
+     -BPF_Fs176400_Fc66_B1},
     {BPF_Fs192000_Fc78_A0,                /* 192kS/s coefficients */
      -BPF_Fs192000_Fc78_B2,
      -BPF_Fs192000_Fc78_B1},
@@ -432,9 +490,15 @@
      -BPF_Fs48000_Fc90_B1}
 #ifdef HIGHER_FS
     ,
+    {BPF_Fs88200_Fc90_A0,                /* 88kS/s coefficients */
+     -BPF_Fs88200_Fc90_B2,
+     -BPF_Fs88200_Fc90_B1},
     {BPF_Fs96000_Fc90_A0,                /* 96kS/s coefficients */
      -BPF_Fs96000_Fc90_B2,
      -BPF_Fs96000_Fc90_B1},
+    {BPF_Fs176400_Fc90_A0,                /* 176kS/s coefficients */
+     -BPF_Fs176400_Fc90_B2,
+     -BPF_Fs176400_Fc90_B1},
     {BPF_Fs192000_Fc90_A0,                /* 192kS/s coefficients */
      -BPF_Fs192000_Fc90_B2,
      -BPF_Fs192000_Fc90_B1}
@@ -466,7 +530,9 @@
     AGC_ATTACK_Fs44100,
     AGC_ATTACK_Fs48000
 #ifdef HIGHER_FS
+    ,AGC_ATTACK_Fs88200
     ,AGC_ATTACK_Fs96000
+    ,AGC_ATTACK_Fs176400
     ,AGC_ATTACK_Fs192000
 #endif
 
@@ -488,7 +554,9 @@
     AGC_DECAY_Fs44100,
     AGC_DECAY_Fs48000
 #ifdef HIGHER_FS
+    ,AGC_DECAY_Fs88200
     ,AGC_DECAY_FS96000
+    ,AGC_DECAY_Fs176400
     ,AGC_DECAY_FS192000
 #endif
 
@@ -583,7 +651,9 @@
     VOL_TC_Fs44100,
     VOL_TC_Fs48000
 #ifdef HIGHER_FS
+    ,VOL_TC_Fs88200
     ,VOL_TC_Fs96000
+    ,VOL_TC_Fs176400
     ,VOL_TC_Fs192000
 #endif
 };
@@ -602,7 +672,9 @@
     MIX_TC_Fs44100,
     MIX_TC_Fs48000
 #ifdef HIGHER_FS
+    ,MIX_TC_Fs88200
     ,MIX_TC_Fs96000
+    ,MIX_TC_Fs176400
     ,MIX_TC_Fs192000
 #endif
 
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
index 8c04847..bab4049 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
@@ -487,6 +487,97 @@
 #define HPF_Fs48000_Gain15_B2                         0.000000
 
 #ifdef HIGHER_FS
+/* Coefficients for sample rate 88200 */
+/* Gain = 1.000000 dB */
+#define HPF_Fs88200_Gain1_A0                          1.094374f
+#define HPF_Fs88200_Gain1_A1                          (-0.641256f)
+#define HPF_Fs88200_Gain1_A2                          0.000000f
+#define HPF_Fs88200_Gain1_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain1_B2                          0.000000f
+/* Gain = 2.000000 dB */
+#define HPF_Fs88200_Gain2_A0                          1.200264f
+#define HPF_Fs88200_Gain2_A1                          (-0.747146f)
+#define HPF_Fs88200_Gain2_A2                          0.000000f
+#define HPF_Fs88200_Gain2_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain2_B2                          0.000000f
+/* Gain = 3.000000 dB */
+#define HPF_Fs88200_Gain3_A0                          1.319074f
+#define HPF_Fs88200_Gain3_A1                          (-0.865956f)
+#define HPF_Fs88200_Gain3_A2                          0.000000f
+#define HPF_Fs88200_Gain3_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain3_B2                          0.000000f
+/* Gain = 4.000000 dB */
+#define HPF_Fs88200_Gain4_A0                          1.452380f
+#define HPF_Fs88200_Gain4_A1                          (-0.999263f)
+#define HPF_Fs88200_Gain4_A2                          0.000000f
+#define HPF_Fs88200_Gain4_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain4_B2                          0.000000f
+/* Gain = 5.000000 dB */
+#define HPF_Fs88200_Gain5_A0                          1.601953f
+#define HPF_Fs88200_Gain5_A1                          (-1.148836f)
+#define HPF_Fs88200_Gain5_A2                          0.000000f
+#define HPF_Fs88200_Gain5_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain5_B2                          0.000000f
+/* Gain = 6.000000 dB */
+#define HPF_Fs88200_Gain6_A0                          1.769777f
+#define HPF_Fs88200_Gain6_A1                          (-1.316659f)
+#define HPF_Fs88200_Gain6_A2                          0.000000f
+#define HPF_Fs88200_Gain6_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain6_B2                          0.000000f
+/* Gain = 7.000000 dB */
+#define HPF_Fs88200_Gain7_A0                          1.958078f
+#define HPF_Fs88200_Gain7_A1                          (-1.504960f)
+#define HPF_Fs88200_Gain7_A2                          0.000000f
+#define HPF_Fs88200_Gain7_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain7_B2                          0.000000f
+/* Gain = 8.000000 dB */
+#define HPF_Fs88200_Gain8_A0                          2.169355f
+#define HPF_Fs88200_Gain8_A1                          (-1.716238f)
+#define HPF_Fs88200_Gain8_A2                          0.000000f
+#define HPF_Fs88200_Gain8_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain8_B2                          0.000000f
+/* Gain = 9.000000 dB */
+#define HPF_Fs88200_Gain9_A0                          2.406412f
+#define HPF_Fs88200_Gain9_A1                          (-1.953295f)
+#define HPF_Fs88200_Gain9_A2                          0.000000f
+#define HPF_Fs88200_Gain9_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain9_B2                          0.000000f
+/* Gain = 10.000000 dB */
+#define HPF_Fs88200_Gain10_A0                          2.672395f
+#define HPF_Fs88200_Gain10_A1                          (-2.219277f)
+#define HPF_Fs88200_Gain10_A2                          0.000000f
+#define HPF_Fs88200_Gain10_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain10_B2                          0.000000f
+/* Gain = 11.000000 dB */
+#define HPF_Fs88200_Gain11_A0                          2.970832f
+#define HPF_Fs88200_Gain11_A1                          (-2.517714f)
+#define HPF_Fs88200_Gain11_A2                          0.000000f
+#define HPF_Fs88200_Gain11_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain11_B2                          0.000000f
+/* Gain = 12.000000 dB */
+#define HPF_Fs88200_Gain12_A0                          3.305684f
+#define HPF_Fs88200_Gain12_A1                          (-2.852566f)
+#define HPF_Fs88200_Gain12_A2                          0.000000f
+#define HPF_Fs88200_Gain12_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain12_B2                          0.000000f
+/* Gain = 13.000000 dB */
+#define HPF_Fs88200_Gain13_A0                          3.681394f
+#define HPF_Fs88200_Gain13_A1                          (-3.228276f)
+#define HPF_Fs88200_Gain13_A2                          0.000000f
+#define HPF_Fs88200_Gain13_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain13_B2                          0.000000f
+/* Gain = 14.000000 dB */
+#define HPF_Fs88200_Gain14_A0                          4.102947f
+#define HPF_Fs88200_Gain14_A1                          (-3.649830f)
+#define HPF_Fs88200_Gain14_A2                          0.000000f
+#define HPF_Fs88200_Gain14_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain14_B2                          0.000000f
+/* Gain = 15.000000 dB */
+#define HPF_Fs88200_Gain15_A0                          4.575938f
+#define HPF_Fs88200_Gain15_A1                          (-4.122820f)
+#define HPF_Fs88200_Gain15_A2                          0.000000f
+#define HPF_Fs88200_Gain15_B1                          (-0.546882f)
+#define HPF_Fs88200_Gain15_B2                          0.000000f
 
 /* Coefficients for sample rate 96000Hz */
                                                                  /* Gain =  1.000000 dB */
@@ -580,6 +671,98 @@
 #define HPF_Fs96000_Gain15_B1                         (-0.577350)
 #define HPF_Fs96000_Gain15_B2                         0.000000
 
+/* Coefficients for sample rate 176400 */
+/* Gain = 1.000000 dB */
+#define HPF_Fs176400_Gain1_A0                          1.106711f
+#define HPF_Fs176400_Gain1_A1                          (-0.855807f)
+#define HPF_Fs176400_Gain1_A2                          0.000000f
+#define HPF_Fs176400_Gain1_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain1_B2                          0.000000f
+/* Gain = 2.000000 dB */
+#define HPF_Fs176400_Gain2_A0                          1.226443f
+#define HPF_Fs176400_Gain2_A1                          (-0.975539f)
+#define HPF_Fs176400_Gain2_A2                          0.000000f
+#define HPF_Fs176400_Gain2_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain2_B2                          0.000000f
+/* Gain = 3.000000 dB */
+#define HPF_Fs176400_Gain3_A0                          1.360784f
+#define HPF_Fs176400_Gain3_A1                          (-1.109880f)
+#define HPF_Fs176400_Gain3_A2                          0.000000f
+#define HPF_Fs176400_Gain3_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain3_B2                          0.000000f
+/* Gain = 4.000000 dB */
+#define HPF_Fs176400_Gain4_A0                          1.511517f
+#define HPF_Fs176400_Gain4_A1                          (-1.260613f)
+#define HPF_Fs176400_Gain4_A2                          0.000000f
+#define HPF_Fs176400_Gain4_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain4_B2                          0.000000f
+/* Gain = 5.000000 dB */
+#define HPF_Fs176400_Gain5_A0                          1.680643f
+#define HPF_Fs176400_Gain5_A1                          (-1.429739f)
+#define HPF_Fs176400_Gain5_A2                          0.000000f
+#define HPF_Fs176400_Gain5_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain5_B2                          0.000000f
+/* Gain = 6.000000 dB */
+#define HPF_Fs176400_Gain6_A0                          1.870405f
+#define HPF_Fs176400_Gain6_A1                          (-1.619501f)
+#define HPF_Fs176400_Gain6_A2                          0.000000f
+#define HPF_Fs176400_Gain6_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain6_B2                          0.000000f
+/* Gain = 7.000000 dB */
+#define HPF_Fs176400_Gain7_A0                          2.083321f
+#define HPF_Fs176400_Gain7_A1                          (-1.832417f)
+#define HPF_Fs176400_Gain7_A2                          0.000000f
+#define HPF_Fs176400_Gain7_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain7_B2                          0.000000f
+/* Gain = 8.000000 dB */
+#define HPF_Fs176400_Gain8_A0                          2.322217f
+#define HPF_Fs176400_Gain8_A1                          (-2.071313f)
+#define HPF_Fs176400_Gain8_A2                          0.000000f
+#define HPF_Fs176400_Gain8_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain8_B2                          0.000000f
+/* Gain = 9.000000 dB */
+#define HPF_Fs176400_Gain9_A0                          2.590263f
+#define HPF_Fs176400_Gain9_A1                          (-2.339359f)
+#define HPF_Fs176400_Gain9_A2                          0.000000f
+#define HPF_Fs176400_Gain9_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain9_B2                          0.000000f
+/* Gain = 10.000000 dB */
+#define HPF_Fs176400_Gain10_A0                          2.891016f
+#define HPF_Fs176400_Gain10_A1                          (-2.640112f)
+#define HPF_Fs176400_Gain10_A2                          0.000000f
+#define HPF_Fs176400_Gain10_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain10_B2                          0.000000f
+/* Gain = 11.000000 dB */
+#define HPF_Fs176400_Gain11_A0                          3.228465f
+#define HPF_Fs176400_Gain11_A1                          (-2.977561f)
+#define HPF_Fs176400_Gain11_A2                          0.000000f
+#define HPF_Fs176400_Gain11_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain11_B2                          0.000000f
+/* Gain = 12.000000 dB */
+#define HPF_Fs176400_Gain12_A0                          3.607090f
+#define HPF_Fs176400_Gain12_A1                          (-3.356186f)
+#define HPF_Fs176400_Gain12_A2                          0.000000f
+#define HPF_Fs176400_Gain12_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain12_B2                          0.000000f
+/* Gain = 13.000000 dB */
+#define HPF_Fs176400_Gain13_A0                          4.031914f
+#define HPF_Fs176400_Gain13_A1                          (-3.781010f)
+#define HPF_Fs176400_Gain13_A2                          0.000000f
+#define HPF_Fs176400_Gain13_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain13_B2                          0.000000f
+/* Gain = 14.000000 dB */
+#define HPF_Fs176400_Gain14_A0                          4.508575f
+#define HPF_Fs176400_Gain14_A1                          (-4.257671f)
+#define HPF_Fs176400_Gain14_A2                          0.000000f
+#define HPF_Fs176400_Gain14_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain14_B2                          0.000000f
+/* Gain = 15.000000 dB */
+#define HPF_Fs176400_Gain15_A0                          5.043397f
+#define HPF_Fs176400_Gain15_A1                          (-4.792493f)
+#define HPF_Fs176400_Gain15_A2                          0.000000f
+#define HPF_Fs176400_Gain15_B1                          (-0.749096f)
+#define HPF_Fs176400_Gain15_B2                          0.000000f
+
 /* Coefficients for sample rate 192000Hz */
                                                                   /* Gain =  1.000000 dB */
 #define HPF_Fs192000_Gain1_A0                          1.107823
@@ -1216,4 +1399,4 @@
 
 
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
index 7b85f23..62b4c73 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -71,7 +71,8 @@
     ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
      (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)      &&
      (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)      &&
-     (pParams->SampleRate != LVM_FS_96000) && (pParams->SampleRate != LVM_FS_192000))      ||
+     (pParams->SampleRate != LVM_FS_88200) && (pParams->SampleRate != LVM_FS_96000) &&
+     (pParams->SampleRate != LVM_FS_176400) && (pParams->SampleRate != LVM_FS_192000))      ||
 #else
         ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
         (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)       &&
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
index ade329b..0669a81 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -233,7 +233,13 @@
          * Set the capabilities
          */
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_192000;
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
+                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
+                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
+                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
+                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
+                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
+                                           LVDBE_CAP_FS_192000;
 #else
         DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
 #endif
@@ -270,7 +276,13 @@
          * Set the capabilities
          */
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_192000;
+        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
+                                         LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
+                                         LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
+                                         LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
+                                         LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
+                                         LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
+                                         LVEQNB_CAP_FS_192000;
 #else
         EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
 #endif
@@ -747,7 +759,13 @@
          * Set the initialisation capabilities
          */
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_192000;
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 |
+                                           LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 |
+                                           LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 |
+                                           LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 |
+                                           LVDBE_CAP_FS_48000 | LVDBE_CAP_FS_88200 |
+                                           LVDBE_CAP_FS_96000 | LVDBE_CAP_FS_176400 |
+                                           LVDBE_CAP_FS_192000;
 #else
         DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
 #endif
@@ -805,7 +823,13 @@
          * Set the initialisation capabilities
          */
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_192000;
+        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 |
+                                            LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 |
+                                            LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 |
+                                            LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 |
+                                            LVEQNB_CAP_FS_48000 | LVEQNB_CAP_FS_88200 |
+                                            LVEQNB_CAP_FS_96000 | LVEQNB_CAP_FS_176400 |
+                                            LVEQNB_CAP_FS_192000;
 #else
         EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
 #endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
index 199ddde..a5356d2 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
@@ -269,6 +269,53 @@
                      -HPF_Fs48000_Gain15_B1}
 #ifdef HIGHER_FS
                     ,
+                    /* 88kHz Sampling rate */
+                    {HPF_Fs88200_Gain1_A1,             /* Gain Setting  1 */
+                    HPF_Fs88200_Gain1_A0,
+                    -HPF_Fs88200_Gain1_B1},
+                    {HPF_Fs88200_Gain2_A1,             /* Gain Setting  2 */
+                    HPF_Fs88200_Gain2_A0,
+                    -HPF_Fs88200_Gain2_B1},
+                    {HPF_Fs88200_Gain3_A1,             /* Gain Setting  3 */
+                    HPF_Fs88200_Gain3_A0,
+                    -HPF_Fs88200_Gain3_B1},
+                    {HPF_Fs88200_Gain4_A1,             /* Gain Setting  4 */
+                    HPF_Fs88200_Gain4_A0,
+                    -HPF_Fs88200_Gain4_B1},
+                    {HPF_Fs88200_Gain5_A1,             /* Gain Setting  5 */
+                    HPF_Fs88200_Gain5_A0,
+                    -HPF_Fs88200_Gain5_B1},
+                    {HPF_Fs88200_Gain6_A1,             /* Gain Setting  6 */
+                    HPF_Fs88200_Gain6_A0,
+                    -HPF_Fs88200_Gain6_B1},
+                    {HPF_Fs88200_Gain7_A1,             /* Gain Setting  7 */
+                    HPF_Fs88200_Gain7_A0,
+                    -HPF_Fs88200_Gain7_B1},
+                    {HPF_Fs88200_Gain8_A1,             /* Gain Setting  8 */
+                    HPF_Fs88200_Gain8_A0,
+                    -HPF_Fs88200_Gain8_B1},
+                    {HPF_Fs88200_Gain9_A1,             /* Gain Setting  9 */
+                    HPF_Fs88200_Gain9_A0,
+                    -HPF_Fs88200_Gain9_B1},
+                    {HPF_Fs88200_Gain10_A1,             /* Gain Setting  10 */
+                    HPF_Fs88200_Gain10_A0,
+                    -HPF_Fs88200_Gain10_B1},
+                    {HPF_Fs88200_Gain11_A1,             /* Gain Setting  11 */
+                    HPF_Fs88200_Gain11_A0,
+                    -HPF_Fs88200_Gain11_B1},
+                    {HPF_Fs88200_Gain12_A1,             /* Gain Setting  12 */
+                    HPF_Fs88200_Gain12_A0,
+                    -HPF_Fs88200_Gain12_B1},
+                    {HPF_Fs88200_Gain13_A1,             /* Gain Setting  13 */
+                    HPF_Fs88200_Gain13_A0,
+                    -HPF_Fs88200_Gain13_B1},
+                    {HPF_Fs88200_Gain14_A1,             /* Gain Setting  14 */
+                    HPF_Fs88200_Gain14_A0,
+                    -HPF_Fs88200_Gain14_B1},
+                    {HPF_Fs88200_Gain15_A1,             /* Gain Setting  15 */
+                    HPF_Fs88200_Gain15_A0,
+                    -HPF_Fs88200_Gain15_B1},
+
                     /* 96kHz sampling rate */
                     {HPF_Fs96000_Gain1_A1,             /* Gain setting 1 */
                     HPF_Fs96000_Gain1_A0,
@@ -316,6 +363,53 @@
                     HPF_Fs96000_Gain15_A0,
                     -HPF_Fs96000_Gain15_B1},
 
+                    /* 176kHz Sampling rate */
+                    {HPF_Fs176400_Gain1_A1,             /* Gain Setting  1 */
+                    HPF_Fs176400_Gain1_A0,
+                    -HPF_Fs176400_Gain1_B1},
+                    {HPF_Fs176400_Gain2_A1,             /* Gain Setting  2 */
+                    HPF_Fs176400_Gain2_A0,
+                    -HPF_Fs176400_Gain2_B1},
+                    {HPF_Fs176400_Gain3_A1,             /* Gain Setting  3 */
+                    HPF_Fs176400_Gain3_A0,
+                    -HPF_Fs176400_Gain3_B1},
+                    {HPF_Fs176400_Gain4_A1,             /* Gain Setting  4 */
+                    HPF_Fs176400_Gain4_A0,
+                    -HPF_Fs176400_Gain4_B1},
+                    {HPF_Fs176400_Gain5_A1,             /* Gain Setting  5 */
+                    HPF_Fs176400_Gain5_A0,
+                    -HPF_Fs176400_Gain5_B1},
+                    {HPF_Fs176400_Gain6_A1,             /* Gain Setting  6 */
+                    HPF_Fs176400_Gain6_A0,
+                    -HPF_Fs176400_Gain6_B1},
+                    {HPF_Fs176400_Gain7_A1,             /* Gain Setting  7 */
+                    HPF_Fs176400_Gain7_A0,
+                    -HPF_Fs176400_Gain7_B1},
+                    {HPF_Fs176400_Gain8_A1,             /* Gain Setting  8 */
+                    HPF_Fs176400_Gain8_A0,
+                    -HPF_Fs176400_Gain8_B1},
+                    {HPF_Fs176400_Gain9_A1,             /* Gain Setting  9 */
+                    HPF_Fs176400_Gain9_A0,
+                    -HPF_Fs176400_Gain9_B1},
+                    {HPF_Fs176400_Gain10_A1,             /* Gain Setting  10 */
+                    HPF_Fs176400_Gain10_A0,
+                    -HPF_Fs176400_Gain10_B1},
+                    {HPF_Fs176400_Gain11_A1,             /* Gain Setting  11 */
+                    HPF_Fs176400_Gain11_A0,
+                    -HPF_Fs176400_Gain11_B1},
+                    {HPF_Fs176400_Gain12_A1,             /* Gain Setting  12 */
+                    HPF_Fs176400_Gain12_A0,
+                    -HPF_Fs176400_Gain12_B1},
+                    {HPF_Fs176400_Gain13_A1,             /* Gain Setting  13 */
+                    HPF_Fs176400_Gain13_A0,
+                    -HPF_Fs176400_Gain13_B1},
+                    {HPF_Fs176400_Gain14_A1,             /* Gain Setting  14 */
+                    HPF_Fs176400_Gain14_A0,
+                    -HPF_Fs176400_Gain14_B1},
+                    {HPF_Fs176400_Gain15_A1,             /* Gain Setting  15 */
+                    HPF_Fs176400_Gain15_A0,
+                    -HPF_Fs176400_Gain15_B1},
+
                     /* 192kHz sampling rate */
                     {HPF_Fs192000_Gain1_A1,             /* Gain setting 1 */
                     HPF_Fs192000_Gain1_A0,
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index 303b62d..59586e0 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -169,8 +169,10 @@
     LVM_FS_44100 = 7,
     LVM_FS_48000 = 8,
 #ifdef HIGHER_FS
-    LVM_FS_96000 = 9,
-    LVM_FS_192000 = 10,
+    LVM_FS_88200 = 9,
+    LVM_FS_96000 = 10,
+    LVM_FS_176400 = 11,
+    LVM_FS_192000 = 12,
 #endif
     LVM_FS_INVALID = LVM_MAXENUM-1,
     LVM_FS_DUMMY = LVM_MAXENUM
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
index e7fdbf6..385dbcf 100644
--- a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -201,8 +201,10 @@
 #define LVEQNB_CAP_FS_44100                128
 #define LVEQNB_CAP_FS_48000                256
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-#define LVEQNB_CAP_FS_96000                512
-#define LVEQNB_CAP_FS_192000               1024
+#define LVEQNB_CAP_FS_88200                512
+#define LVEQNB_CAP_FS_96000                1024
+#define LVEQNB_CAP_FS_176400               2048
+#define LVEQNB_CAP_FS_192000               4096
 #endif
 
 typedef enum
@@ -217,8 +219,10 @@
     LVEQNB_FS_44100 = 7,
     LVEQNB_FS_48000 = 8,
 #ifdef HIGHER_FS
-    LVEQNB_FS_96000 = 9,
-    LVEQNB_FS_192000 = 10,
+    LVEQNB_FS_88200 = 9,
+    LVEQNB_FS_96000 = 10,
+    LVEQNB_FS_176400 = 11,
+    LVEQNB_FS_192000 = 12,
 #endif
     LVEQNB_FS_MAX   = LVM_MAXINT_32
 } LVEQNB_Fs_en;
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
index 42ea46f..755141e 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
@@ -109,7 +109,9 @@
 #define LVEQNB_2PiOn_48000                               0.000131f
 
 #ifdef HIGHER_FS
+#define LVEQNB_2PiOn_88200                               0.000071f
 #define LVEQNB_2PiOn_96000                               0.000065f
+#define LVEQNB_2PiOn_176400                              0.000036f
 #define LVEQNB_2PiOn_192000                              0.000033f
 #endif
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
index 563181c..453c42d 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
@@ -46,7 +46,9 @@
                                               32000,
                                               44100,
                                               48000,
+                                              88200,
                                               96000,
+                                              176400,
                                               192000
 };
 #else
@@ -82,7 +84,9 @@
                                                LVEQNB_2PiOn_44100,
                                                LVEQNB_2PiOn_48000
 #ifdef HIGHER_FS
+                                              ,LVEQNB_2PiOn_88200
                                               ,LVEQNB_2PiOn_96000
+                                              ,LVEQNB_2PiOn_176400
                                               ,LVEQNB_2PiOn_192000
 #endif
                                                };
@@ -249,30 +253,4 @@
                                           16586,                       /* a2 */
                                           -44};                        /* a3 */
 
-/************************************************************************************/
-/*                                                                                  */
-/*  Bypass mixer time constants (100ms)                                             */
-/*                                                                                  */
-/************************************************************************************/
 
-#define LVEQNB_MIX_TC_Fs8000    32580         /* Floating point value 0.994262695 */
-#define LVEQNB_MIX_TC_Fs11025   32632         /* Floating point value 0.995849609 */
-#define LVEQNB_MIX_TC_Fs12000   32643         /* Floating point value 0.996185303 */
-#define LVEQNB_MIX_TC_Fs16000   32674         /* Floating point value 0.997131348 */
-#define LVEQNB_MIX_TC_Fs22050   32700         /* Floating point value 0.997924805 */
-#define LVEQNB_MIX_TC_Fs24000   32705         /* Floating point value 0.998077393 */
-#define LVEQNB_MIX_TC_Fs32000   32721         /* Floating point value 0.998565674 */
-#define LVEQNB_MIX_TC_Fs44100   32734         /* Floating point value 0.998962402 */
-#define LVEQNB_MIX_TC_Fs48000   32737         /* Floating point value 0.999053955 */
-
-
-const LVM_INT16 LVEQNB_MixerTCTable[] = {
-    LVEQNB_MIX_TC_Fs8000,
-    LVEQNB_MIX_TC_Fs11025,
-    LVEQNB_MIX_TC_Fs12000,
-    LVEQNB_MIX_TC_Fs16000,
-    LVEQNB_MIX_TC_Fs22050,
-    LVEQNB_MIX_TC_Fs24000,
-    LVEQNB_MIX_TC_Fs32000,
-    LVEQNB_MIX_TC_Fs44100,
-    LVEQNB_MIX_TC_Fs48000};
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index ff7475e..c915ac0 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -123,7 +123,7 @@
 #ifndef HIGHER_FS
 #define LVREV_NUM_FS                        9           /* Number of supported sample rates */
 #else
-#define LVREV_NUM_FS                       11           /* Number of supported sample rates */
+#define LVREV_NUM_FS                       13           /* Number of supported sample rates */
 #endif
 
 #define LVREV_MAXBLKSIZE_LIMIT             64           /* Maximum block size low limit */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
index 8c7807f..dfed28e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
@@ -68,7 +68,8 @@
         (pNewParams->SampleRate != LVM_FS_44100) &&
         (pNewParams->SampleRate != LVM_FS_48000)
 #ifdef HIGHER_FS
-        && (pNewParams->SampleRate != LVM_FS_96000) && (pNewParams->SampleRate != LVM_FS_192000)
+        && (pNewParams->SampleRate != LVM_FS_88200) && (pNewParams->SampleRate != LVM_FS_96000)
+        && (pNewParams->SampleRate != LVM_FS_176400) && (pNewParams->SampleRate != LVM_FS_192000)
 #endif
         )
 #ifdef SUPPORT_MC
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
index b3edc60..1058740 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
@@ -52,7 +52,9 @@
     32000,
     44100,
     48000,
+    88200,
     96000,
+    176400,
     192000
 };
 #endif
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
index a750bb0..ee07e2e 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -46,7 +46,7 @@
 #ifndef HIGHER_FS
 #define LVPSA_NR_SUPPORTED_RATE          9      /* From 8000Hz to 48000Hz*/
 #else
-#define LVPSA_NR_SUPPORTED_RATE          11      /* From 8000Hz to 192000Hz*/
+#define LVPSA_NR_SUPPORTED_RATE          13      /* From 8000Hz to 192000Hz*/
 #endif
 #define LVPSA_NR_SUPPORTED_SPEED         3      /* LOW, MEDIUM, HIGH                                                */
 
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
index 1287503..f8af496 100644
--- a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -54,7 +54,9 @@
                                                 32000,
                                                 44100,
                                                 48000,
+                                                88200,
                                                 96000,
+                                               176400,
                                                192000};                  /* 192kS/s */
 #endif
 
@@ -78,7 +80,9 @@
                                                     48696,
                                                     44739
 #ifdef HIGHER_FS
+                                                    ,24348
                                                     ,22369
+                                                    ,12174
                                                     ,11185                  /* 192kS/s */
 #endif
                                                };
@@ -105,7 +109,9 @@
                                                         882,
                                                         960
 #ifdef HIGHER_FS
+                                                        ,1764
                                                         ,1920
+                                                        ,3528
                                                         ,3840                  /* 192kS/s */
 #endif
                                                     };
@@ -128,7 +134,9 @@
                                                         30,                   /* 44100 S/s  */
                                                         32                    /* 48000 S/s  */
 #ifdef HIGHER_FS
+                                                       ,60                   /* 88200 S/s  */
                                                        ,64                   /* 96000 S/s  */
+                                                       ,120                  /* 176400 S/s  */
                                                        ,128                  /*192000 S/s  */
 #endif
                                                   };
@@ -153,7 +161,9 @@
                                                  4781,
                                                  4392
 #ifdef HIGHER_FS
+                                                ,2390
                                                 ,2196
+                                                ,1195
                                                 ,1098    /* 192kS/s */
 #endif
                                              };
@@ -169,7 +179,9 @@
                                                       0.1459089f,
                                                       0.1340372f
 #ifdef HIGHER_FS
+                                                     ,0.0729476f
                                                      ,0.0670186f
+                                                     ,0.0364738f
                                                      ,0.0335093f    /* 192kS/s */
 #endif
                                                    };
@@ -352,7 +364,9 @@
                                           /* 48kS/s */
                                          {-0.9932638457976282f,0.0066249934025109f},
 #ifdef HIGHER_FS
+                                         {-0.9931269618682563f,0.0067592649720609f},
                                          {-0.9932638457976282f,0.0066249934025109f},
+                                         {-0.9931269618682563f,0.0067592649720609f},
                                          {-0.9932638457976282f,0.0066249934025109f},
 #endif
                                          /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
@@ -368,7 +382,9 @@
                                           /* 48kS/s */
                                          {-0.9540119562298059f,0.0445343819446862f},
 #ifdef HIGHER_FS
+                                         {-0.9531011912040412f,0.0453995238058269f},
                                          {-0.9540119562298059f,0.0445343819446862f},
+                                         {-0.9531011912040412f,0.0453995238058269f},
                                          {-0.9540119562298059f,0.0445343819446862f},
 #endif
                                           /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
@@ -383,7 +399,9 @@
                                            /* 48kS/s */
                                          {-0.7274807319045067f,0.2356666540727019f}
 #ifdef HIGHER_FS
+                                        ,{-0.7229706319049001f,0.2388987224549055f}
                                         ,{-0.7274807319045067f,0.2356666540727019f}
+                                        ,{-0.7229706319049001f,0.2388987224549055f}
                                         ,{-0.7274807319045067f,0.2356666540727019f}
 #endif
                                         };
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
index 0c2fe53..e45d81f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
@@ -152,6 +152,24 @@
 #define CS_SIDE_48000_SCALE                          14
 
 #ifdef HIGHER_FS
+/* Coefficients for 88200Hz sample rate.
+ * The filter coefficients are obtained by carrying out
+ * state-space analysis using the coefficients available
+ * for 44100Hz.
+ */
+#define CS_MIDDLE_88200_A0                     0.233846f
+#define CS_MIDDLE_88200_A1                     (-0.232657f)
+#define CS_MIDDLE_88200_A2                     0.000000f
+#define CS_MIDDLE_88200_B1                     (-0.992747f)
+#define CS_MIDDLE_88200_B2                     0.000000f
+#define CS_MIDDLE_88200_SCALE                  15
+#define CS_SIDE_88200_A0                       0.231541f
+#define CS_SIDE_88200_A1                       (-0.289586f)
+#define CS_SIDE_88200_A2                       0.058045f
+#define CS_SIDE_88200_B1                       (-1.765300f)
+#define CS_SIDE_88200_B2                       0.769816f
+#define CS_SIDE_88200_SCALE                    14
+
 /* Stereo Enhancer coefficients for 96000Hz sample rate, scaled with  0.165*/
 /* high pass filter with cutoff frequency 102.18 Hz*/
 #define CS_MIDDLE_96000_A0                     0.235532
@@ -160,13 +178,33 @@
 #define CS_MIDDLE_96000_B1                    (-0.993334)
 #define CS_MIDDLE_96000_B2                     0.000000
 #define CS_MIDDLE_96000_SCALE                        15
-/* bandpass filter with fc1 270 and fc2 3703, designed using 2nd order butterworth */
-#define CS_SIDE_96000_A0                     0.016727
-#define CS_SIDE_96000_A1                     0.000000
-#define CS_SIDE_96000_A2                    (-0.016727)
-#define CS_SIDE_96000_B1                    (-1.793372)
-#define CS_SIDE_96000_B2                     0.797236
-#define CS_SIDE_96000_SCALE                        14
+/* Coefficients calculated using tf2ss and ss2tf functions based on
+ * coefficients available for 48000Hz sampling frequency
+ */
+#define CS_SIDE_96000_A0                     0.224326f
+#define CS_SIDE_96000_A1                     (-0.294937f)
+#define CS_SIDE_96000_A2                     0.070611f
+#define CS_SIDE_96000_B1                     (-1.792166f)
+#define CS_SIDE_96000_B2                     0.795830f
+#define CS_SIDE_96000_SCALE                  14
+
+/* Stereo Enhancer coefficients for 176400Hz sample rate.
+ * The filter coefficients are obtained by carrying out
+ * state-space analysis using the coefficients available
+ * for 44100Hz.
+ */
+#define CS_MIDDLE_176400_A0                     0.233973f
+#define CS_MIDDLE_176400_A1                     (-0.233378f)
+#define CS_MIDDLE_176400_A2                     0.000000f
+#define CS_MIDDLE_176400_B1                     (-0.996367f)
+#define CS_MIDDLE_176400_B2                     0.000000f
+#define CS_MIDDLE_176400_SCALE                  15
+#define CS_SIDE_176400_A0                       0.199836f
+#define CS_SIDE_176400_A1                       (-0.307544f)
+#define CS_SIDE_176400_A2                       0.107708f
+#define CS_SIDE_176400_B1                       (-1.876572f)
+#define CS_SIDE_176400_B2                       0.877771f
+#define CS_SIDE_176400_SCALE                    14
 
 /* Stereo Enhancer coefficients for 192000Hz sample rate, scaled with  0.1689*/
 #define CS_MIDDLE_192000_A0                     0.241219
@@ -175,13 +213,15 @@
 #define CS_MIDDLE_192000_B1                    (-0.996661)
 #define CS_MIDDLE_192000_B2                     0.000000
 #define CS_MIDDLE_192000_SCALE                        15
-/* bandpass filter with fc1 270 and fc2 3703, designed using 2nd order butterworth */
-#define CS_SIDE_192000_A0                     0.008991
-#define CS_SIDE_192000_A1                    (-0.000000)
-#define CS_SIDE_192000_A2                    (-0.008991)
-#define CS_SIDE_192000_B1                    (-1.892509)
-#define CS_SIDE_192000_B2                     0.893524
-#define CS_SIDE_192000_SCALE                       14
+/* Coefficients calculated using tf2ss and ss2tf functions based on
+ * coefficients available for 48000Hz sampling frequency
+ */
+#define CS_SIDE_192000_A0                    0.196039f
+#define CS_SIDE_192000_A1                    (-0.311027f)
+#define CS_SIDE_192000_A2                    0.114988f
+#define CS_SIDE_192000_B1                    (-1.891380f)
+#define CS_SIDE_192000_B2                    0.8923460f
+#define CS_SIDE_192000_SCALE                 14
 #endif
 
 /************************************************************************************/
@@ -199,7 +239,13 @@
 #define LVCS_STEREODELAY_CS_24KHZ                   279         /* Sample rate 24kS/s */
 #define LVCS_STEREODELAY_CS_32KHZ                   372         /* Sample rate 32kS/s */
 #define LVCS_STEREODELAY_CS_44KHZ                   512         /* Sample rate 44kS/s */
+// TODO: this should linearly scale by frequency but is limited to 512 frames until
+// we ensure enough buffer size has been allocated.
 #define LVCS_STEREODELAY_CS_48KHZ                   512         /* Sample rate 48kS/s */
+#define LVCS_STEREODELAY_CS_88KHZ                   512         /* Sample rate 88.2kS/s */
+#define LVCS_STEREODELAY_CS_96KHZ                   512         /* Sample rate 96kS/s */
+#define LVCS_STEREODELAY_CS_176KHZ                  512         /* Sample rate 176.4kS/s */
+#define LVCS_STEREODELAY_CS_192KHZ                  512         /* Sample rate 196kS/s */
 
 /* Reverb coefficients for 8000 Hz sample rate, scaled with 1.038030 */
 #define CS_REVERB_8000_A0                          0.667271
@@ -275,6 +321,14 @@
 #define CS_REVERB_48000_SCALE                        14
 
 #ifdef HIGHER_FS
+/* Reverb coefficients for 88200Hz sample rate, scaled with 0.8 */
+/* Band pass filter with fc1=500 and fc2=8000 */
+#define CS_REVERB_88200_A0                       0.171901f
+#define CS_REVERB_88200_A1                       0.000000f
+#define CS_REVERB_88200_A2                      (-0.171901f)
+#define CS_REVERB_88200_B1                      (-1.553948f)
+#define CS_REVERB_88200_B2                      (0.570248f)
+#define CS_REVERB_88200_SCALE                      14
 /* Reverb coefficients for 96000Hz sample rate, scaled with 0.8 */
 /* Band pass filter with fc1=500 and fc2=8000*/
 #define CS_REVERB_96000_A0                       0.1602488
@@ -284,6 +338,14 @@
 #define CS_REVERB_96000_B2                       0.599377
 #define CS_REVERB_96000_SCALE                        14
 
+/* Reverb coefficients for 176400Hz sample rate, scaled with 0.8 */
+/* Band pass filter with fc1=500 and fc2=8000 */
+#define CS_REVERB_176400_A0                       0.094763f
+#define CS_REVERB_176400_A1                       0.000000f
+#define CS_REVERB_176400_A2                      (-0.094763f)
+#define CS_REVERB_176400_B1                      (-1.758593f)
+#define CS_REVERB_176400_B2                      (0.763091f)
+#define CS_REVERB_176400_SCALE                      14
 /* Reverb coefficients for 192000Hz sample rate, scaled with 0.8 */
 /* Band pass filter with fc1=500 and fc2=8000*/
 #define CS_REVERB_192000_A0                       0.0878369
@@ -446,6 +508,24 @@
 
 
 #ifdef HIGHER_FS
+/* Equaliser coefficients for 88200Hz sample rate.
+ * The filter coefficients are obtained by carrying out
+ * state-space analysis using the coefficients available
+ * for 44100Hz.
+ */
+#define CS_EQUALISER_88200_A0                   1.771899f
+#define CS_EQUALISER_88200_A1                   (-2.930762f)
+#define CS_EQUALISER_88200_A2                   1.172175f
+#define CS_EQUALISER_88200_B1                   (-1.438349f)
+#define CS_EQUALISER_88200_B2                   0.442520f
+#define CS_EQUALISER_88200_SCALE                13
+#define CSEX_EQUALISER_88200_A0                 2.675241f
+#define CSEX_EQUALISER_88200_A1                 (-4.466154f)
+#define CSEX_EQUALISER_88200_A2                 1.810305f
+#define CSEX_EQUALISER_88200_B1                 (-0.925350f)
+#define CSEX_EQUALISER_88200_B2                 (-0.066616f)
+#define CSEX_EQUALISER_88200_SCALE              13
+
 #define CS_EQUALISER_96000_A0                    1.784497
 #define CS_EQUALISER_96000_A1                   (-3.001435)
 #define CS_EQUALISER_96000_A2                    1.228422
@@ -458,6 +538,23 @@
 #define CSEX_EQUALISER_96000_B1                 (-0.971718)
 #define CSEX_EQUALISER_96000_B2                 (-0.021216)
 #define CSEX_EQUALISER_96000_SCALE                   13
+/* Equaliser coefficients for 176400Hz sample rate.
+ * The filter coefficients are obtained by carrying out
+ * state-space analysis using the coefficients available
+ * for 44100Hz.
+ */
+#define CS_EQUALISER_176400_A0                  1.883440f
+#define CS_EQUALISER_176400_A1                  (-3.414272f)
+#define CS_EQUALISER_176400_A2                  1.534702f
+#define CS_EQUALISER_176400_B1                  (-1.674614f)
+#define CS_EQUALISER_176400_B2                  0.675827f
+#define CS_EQUALISER_176400_SCALE               13
+#define CSEX_EQUALISER_176400_A0                3.355068f
+#define CSEX_EQUALISER_176400_A1                (-6.112578f)
+#define CSEX_EQUALISER_176400_A2                2.764135f
+#define CSEX_EQUALISER_176400_B1                (-1.268533f)
+#define CSEX_EQUALISER_176400_B2                0.271277f
+#define CSEX_EQUALISER_176400_SCALE             13
 
 #define CS_EQUALISER_192000_A0                    1.889582
 #define CS_EQUALISER_192000_A1                   (-3.456140)
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
index 0765764..a1fb48f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -74,10 +74,18 @@
      (LVM_UINT16 )CS_MIDDLE_48000_SCALE}
 #ifdef HIGHER_FS
     ,
+    {CS_MIDDLE_88200_A0,        /* 88kS/s coefficients */
+     CS_MIDDLE_88200_A1,
+     CS_MIDDLE_88200_B1,
+     (LVM_UINT16)CS_MIDDLE_88200_SCALE},
     {CS_MIDDLE_96000_A0,        /* 96kS/s coefficients */
      CS_MIDDLE_96000_A1,
      CS_MIDDLE_96000_B1,
      (LVM_UINT16 )CS_MIDDLE_96000_SCALE},
+    {CS_MIDDLE_176400_A0,        /* 176kS/s coefficients */
+     CS_MIDDLE_176400_A1,
+     CS_MIDDLE_176400_B1,
+     (LVM_UINT16)CS_MIDDLE_176400_SCALE},
     {CS_MIDDLE_192000_A0,        /* 192kS/s coefficients */
      CS_MIDDLE_192000_A1,
      CS_MIDDLE_192000_B1,
@@ -144,12 +152,24 @@
      (LVM_UINT16 )CS_SIDE_48000_SCALE}
 #ifdef HIGHER_FS
      ,
+    {CS_SIDE_88200_A0,          /* 88kS/s coefficients */
+     CS_SIDE_88200_A1,
+     CS_SIDE_88200_A2,
+     CS_SIDE_88200_B1,
+     CS_SIDE_88200_B2,
+     (LVM_UINT16)CS_SIDE_88200_SCALE},
      {CS_SIDE_96000_A0,          /* 96kS/s coefficients */
      CS_SIDE_96000_A1,
      CS_SIDE_96000_A2,
      CS_SIDE_96000_B1,
      CS_SIDE_96000_B2,
      (LVM_UINT16 )CS_SIDE_96000_SCALE},
+    {CS_SIDE_176400_A0,          /*176kS/s coefficients */
+     CS_SIDE_176400_A1,
+     CS_SIDE_176400_A2,
+     CS_SIDE_176400_B1,
+     CS_SIDE_176400_B2,
+     (LVM_UINT16)CS_SIDE_176400_SCALE},
      {CS_SIDE_192000_A0,          /* 192kS/s coefficients */
      CS_SIDE_192000_A1,
      CS_SIDE_192000_A2,
@@ -223,12 +243,24 @@
      CS_EQUALISER_48000_B2,
      (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
 #ifdef HIGHER_FS
+    {CS_EQUALISER_88200_A0,     /* 88kS/s coeffieients */
+     CS_EQUALISER_88200_A1,
+     CS_EQUALISER_88200_A2,
+     CS_EQUALISER_88200_B1,
+     CS_EQUALISER_88200_B2,
+     (LVM_UINT16)CS_EQUALISER_88200_SCALE},
     {CS_EQUALISER_96000_A0,     /* 96kS/s coefficients */
      CS_EQUALISER_96000_A1,
      CS_EQUALISER_96000_A2,
      CS_EQUALISER_96000_B1,
      CS_EQUALISER_96000_B2,
      (LVM_UINT16 )CS_EQUALISER_96000_SCALE},
+    {CS_EQUALISER_176400_A0,     /* 176kS/s coefficients */
+     CS_EQUALISER_176400_A1,
+     CS_EQUALISER_176400_A2,
+     CS_EQUALISER_176400_B1,
+     CS_EQUALISER_176400_B2,
+     (LVM_UINT16)CS_EQUALISER_176400_SCALE},
     {CS_EQUALISER_192000_A0,     /* 192kS/s coefficients */
      CS_EQUALISER_192000_A1,
      CS_EQUALISER_192000_A2,
@@ -294,12 +326,24 @@
      (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
 #ifdef HIGHER_FS
     ,
+    {CSEX_EQUALISER_88200_A0,   /* 88kS/s coefficients */
+     CSEX_EQUALISER_88200_A1,
+     CSEX_EQUALISER_88200_A2,
+     CSEX_EQUALISER_88200_B1,
+     CSEX_EQUALISER_88200_B2,
+     (LVM_UINT16)CSEX_EQUALISER_88200_SCALE},
     {CSEX_EQUALISER_96000_A0,   /* 96kS/s coefficients */
      CSEX_EQUALISER_96000_A1,
      CSEX_EQUALISER_96000_A2,
      CSEX_EQUALISER_96000_B1,
      CSEX_EQUALISER_96000_B2,
      (LVM_UINT16 )CSEX_EQUALISER_96000_SCALE},
+    {CSEX_EQUALISER_176400_A0,   /* 176kS/s coefficients */
+     CSEX_EQUALISER_176400_A1,
+     CSEX_EQUALISER_176400_A2,
+     CSEX_EQUALISER_176400_B1,
+     CSEX_EQUALISER_176400_B2,
+     (LVM_UINT16)CSEX_EQUALISER_176400_SCALE},
      {CSEX_EQUALISER_192000_A0,   /* 192kS/s coefficients */
      CSEX_EQUALISER_192000_A1,
      CSEX_EQUALISER_192000_A2,
@@ -326,7 +370,12 @@
     LVCS_STEREODELAY_CS_24KHZ,
     LVCS_STEREODELAY_CS_32KHZ,
     LVCS_STEREODELAY_CS_44KHZ,
-    LVCS_STEREODELAY_CS_48KHZ};
+    LVCS_STEREODELAY_CS_48KHZ,
+    LVCS_STEREODELAY_CS_88KHZ,
+    LVCS_STEREODELAY_CS_96KHZ,
+    LVCS_STEREODELAY_CS_176KHZ,
+    LVCS_STEREODELAY_CS_192KHZ,
+};
 
 /************************************************************************************/
 /*                                                                                  */
@@ -392,12 +441,24 @@
      (LVM_UINT16 )CS_REVERB_48000_SCALE}
 #ifdef HIGHER_FS
     ,
+    {CS_REVERB_88200_A0,            /* 88kS/s coefficients */
+     CS_REVERB_88200_A1,
+     CS_REVERB_88200_A2,
+     CS_REVERB_88200_B1,
+     CS_REVERB_88200_B2,
+     (LVM_UINT16)CS_REVERB_88200_SCALE},
     {CS_REVERB_96000_A0,            /* 96kS/s coefficients */
      CS_REVERB_96000_A1,
      CS_REVERB_96000_A2,
      CS_REVERB_96000_B1,
      CS_REVERB_96000_B2,
      (LVM_UINT16 )CS_REVERB_96000_SCALE},
+    {CS_REVERB_176400_A0,            /* 176kS/s coefficients */
+     CS_REVERB_176400_A1,
+     CS_REVERB_176400_A2,
+     CS_REVERB_176400_B1,
+     CS_REVERB_176400_B2,
+     (LVM_UINT16)CS_REVERB_176400_SCALE},
      {CS_REVERB_192000_A0,            /* 192kS/s coefficients */
      CS_REVERB_192000_A1,
      CS_REVERB_192000_A2,
@@ -509,12 +570,14 @@
 #define LVCS_VOL_TC_Fs44100     32734       /* Floating point value 0.998962402 */
 #define LVCS_VOL_TC_Fs48000     32737       /* Floating point value 0.999053955 */
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+#define LVCS_VOL_TC_Fs88200     32751       /* Floating point value 0.999481066 */
 #define LVCS_VOL_TC_Fs96000     32751       /* Floating point value 0.999511703 */   /* Todo @ need to re check this value*/
+#define LVCS_VOL_TC_Fs176400    32759       /* Floating point value 0.999740499 */
 #define LVCS_VOL_TC_Fs192000    32763       /* Floating point value 0.999877925 */  /* Todo @ need to re check this value*/
 #endif
 
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-const LVM_INT16 LVCS_VolumeTCTable[11] = {LVCS_VOL_TC_Fs8000,
+const LVM_INT16 LVCS_VolumeTCTable[13] = {LVCS_VOL_TC_Fs8000,
                                           LVCS_VOL_TC_Fs11025,
                                           LVCS_VOL_TC_Fs12000,
                                           LVCS_VOL_TC_Fs16000,
@@ -523,7 +586,9 @@
                                           LVCS_VOL_TC_Fs32000,
                                           LVCS_VOL_TC_Fs44100,
                                           LVCS_VOL_TC_Fs48000,
+                                          LVCS_VOL_TC_Fs88200,
                                           LVCS_VOL_TC_Fs96000,
+                                          LVCS_VOL_TC_Fs176400,
                                           LVCS_VOL_TC_Fs192000
 };
 #else
@@ -545,7 +610,7 @@
 /*                                                                                  */
 /************************************************************************************/
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
-const LVM_INT32   LVCS_SampleRateTable[11] = {8000,
+const LVM_INT32   LVCS_SampleRateTable[13] = {8000,
                                               11025,
                                               12000,
                                               16000,
@@ -554,7 +619,9 @@
                                               32000,
                                               44100,
                                               48000,
+                                              88200,
                                               96000,
+                                              176400,
                                               192000
 };
 #else
diff --git a/media/libeffects/lvm/tests/lvmtest.cpp b/media/libeffects/lvm/tests/lvmtest.cpp
index 01c5955..99551cc 100644
--- a/media/libeffects/lvm/tests/lvmtest.cpp
+++ b/media/libeffects/lvm/tests/lvmtest.cpp
@@ -447,19 +447,69 @@
                lvmConfigParams_t    *plvmConfigParams,
                LVM_ControlParams_t  *params) {
   LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
-  LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS];  /* Equaliser band definitions */
-  int eqPresetLevel = plvmConfigParams->eqPresetLevel;
-  int nrChannels = plvmConfigParams->nrChannels;
-  params->NrChannels = nrChannels;
 
   /* Set the initial process parameters */
   /* General parameters */
   params->OperatingMode = LVM_MODE_ON;
-  params->SampleRate = LVM_FS_44100;
-  params->SourceFormat = LVM_STEREO;
   params->SpeakerType = LVM_HEADPHONES;
 
-  pContext->pBundledContext->SampleRate = LVM_FS_44100;
+  const int nrChannels = plvmConfigParams->nrChannels;
+  params->NrChannels = nrChannels;
+  if (nrChannels == 1) {
+    params->SourceFormat = LVM_MONO;
+  } else if (nrChannels == 2) {
+    params->SourceFormat = LVM_STEREO;
+  } else if (nrChannels > 2 && nrChannels <= 8) { // FCC_2 FCC_8
+    params->SourceFormat = LVM_MULTICHANNEL;
+  } else {
+      return -EINVAL;
+  }
+
+  LVM_Fs_en sampleRate;
+  switch (plvmConfigParams->samplingFreq) {
+    case 8000:
+      sampleRate = LVM_FS_8000;
+      break;
+    case 11025:
+      sampleRate = LVM_FS_11025;
+      break;
+    case 12000:
+      sampleRate = LVM_FS_12000;
+      break;
+    case 16000:
+      sampleRate = LVM_FS_16000;
+      break;
+    case 22050:
+      sampleRate = LVM_FS_22050;
+      break;
+    case 24000:
+      sampleRate = LVM_FS_24000;
+      break;
+    case 32000:
+      sampleRate = LVM_FS_32000;
+      break;
+    case 44100:
+      sampleRate = LVM_FS_44100;
+      break;
+    case 48000:
+      sampleRate = LVM_FS_48000;
+      break;
+    case 88200:
+      sampleRate = LVM_FS_88200;
+      break;
+    case 96000:
+      sampleRate = LVM_FS_96000;
+      break;
+    case 176400:
+      sampleRate = LVM_FS_176400;
+      break;
+    case 192000:
+      sampleRate = LVM_FS_192000;
+      break;
+    default:
+      return -EINVAL;
+  }
+  params->SampleRate = sampleRate;
 
   /* Concert Sound parameters */
   params->VirtualizerOperatingMode = plvmConfigParams->csEnable;
@@ -468,14 +518,17 @@
   params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
 
   /* N-Band Equaliser parameters */
-  params->EQNB_OperatingMode = plvmConfigParams->eqEnable;
-  params->pEQNB_BandDefinition = &BandDefs[0];
+  const int eqPresetLevel = plvmConfigParams->eqPresetLevel;
+  LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS];  /* Equaliser band definitions */
   for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
     BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
     BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
     BandDefs[i].Gain =
         EQNB_5BandSoftPresets[(FIVEBAND_NUMBANDS * eqPresetLevel) + i];
   }
+  params->EQNB_OperatingMode = plvmConfigParams->eqEnable;
+ // Caution: raw pointer to stack data, stored in instance by LVM_SetControlParameters.
+  params->pEQNB_BandDefinition = &BandDefs[0];
 
   /* Volume Control parameters */
   params->VC_EffectLevel = 0;
@@ -490,16 +543,6 @@
   /* Bass Enhancement parameters */
   params->BE_OperatingMode = plvmConfigParams->bassEnable;
 
-  if (nrChannels == 1) {
-    params->SourceFormat = LVM_MONO;
-  }
-  if (nrChannels == 2) {
-    params->SourceFormat = LVM_STEREO;
-  }
-  if ((nrChannels > 2) && (nrChannels <= 8)) {
-    params->SourceFormat = LVM_MULTICHANNEL;
-  }
-
   /* Activate the initial settings */
   LvmStatus =
       LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
@@ -613,7 +656,9 @@
           samplingFreq != 12000 && samplingFreq != 16000 &&
           samplingFreq != 22050 && samplingFreq != 24000 &&
           samplingFreq != 32000 && samplingFreq != 44100 &&
-          samplingFreq != 48000 && samplingFreq != 96000) {
+          samplingFreq != 48000 && samplingFreq != 88200 &&
+          samplingFreq != 96000 && samplingFreq != 176400 &&
+          samplingFreq != 192000) {
         ALOGE("\nError: Unsupported Sampling Frequency : %d\n", samplingFreq);
         return -1;
       }
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 09e9964..b5860de 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1275,10 +1275,18 @@
         pContext->pBundledContext->SamplesPerSecond = 48000 * NrChannels;
         break;
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    case 88200:
+        SampleRate = LVM_FS_88200;
+        pContext->pBundledContext->SamplesPerSecond = 88200 * NrChannels;
+        break;
     case 96000:
         SampleRate = LVM_FS_96000;
         pContext->pBundledContext->SamplesPerSecond = 96000 * NrChannels;
         break;
+    case 176400:
+        SampleRate = LVM_FS_176400;
+        pContext->pBundledContext->SamplesPerSecond = 176400 * NrChannels;
+        break;
     case 192000:
         SampleRate = LVM_FS_192000;
         pContext->pBundledContext->SamplesPerSecond = 192000 * NrChannels;
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index d558169..602f607 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -675,9 +675,15 @@
         SampleRate = LVM_FS_48000;
         break;
 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
+    case 88200:
+        SampleRate = LVM_FS_88200;
+        break;
     case 96000:
         SampleRate = LVM_FS_96000;
         break;
+    case 176400:
+        SampleRate = LVM_FS_176400;
+        break;
     case 192000:
         SampleRate = LVM_FS_192000;
         break;
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index fb861d7..b5a7172 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -285,6 +285,7 @@
 
 template <>
 const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_STREAM_DEFAULT),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_VOICE_CALL),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_SYSTEM),
     MAKE_STRING_FROM_ENUM(AUDIO_STREAM_RING),
@@ -361,6 +362,22 @@
     TERMINATOR
 };
 
+template <>
+const AudioFlagConverter::Table AudioFlagConverter::mTable[] = {
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_NONE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_AUDIBILITY_ENFORCED),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SECURE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_SCO),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BEACON),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_AV_SYNC),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_HW_HOTWORD),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_BYPASS_MUTE),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_LOW_LATENCY),
+    MAKE_STRING_FROM_ENUM(AUDIO_FLAG_DEEP_BUFFER),
+    TERMINATOR
+};
+
 template class TypeConverter<OutputDeviceTraits>;
 template class TypeConverter<InputDeviceTraits>;
 template class TypeConverter<OutputFlagTraits>;
@@ -374,6 +391,7 @@
 template class TypeConverter<AudioModeTraits>;
 template class TypeConverter<UsageTraits>;
 template class TypeConverter<SourceTraits>;
+template class TypeConverter<AudioFlagTraits>;
 
 bool deviceFromString(const std::string& literalDevice, audio_devices_t& device) {
     return InputDeviceConverter::fromString(literalDevice, device) ||
diff --git a/media/libmedia/include/media/TypeConverter.h b/media/libmedia/include/media/TypeConverter.h
index 86f0d4c..418e09c 100644
--- a/media/libmedia/include/media/TypeConverter.h
+++ b/media/libmedia/include/media/TypeConverter.h
@@ -20,6 +20,7 @@
 #include <string>
 #include <string.h>
 
+#include <vector>
 #include <system/audio.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -30,77 +31,55 @@
 
 namespace android {
 
-struct SampleRateTraits
-{
-    typedef uint32_t Type;
-    typedef SortedVector<Type> Collection;
-};
-struct DeviceTraits
-{
-    typedef audio_devices_t Type;
-    typedef Vector<Type> Collection;
-};
-struct OutputDeviceTraits : public DeviceTraits {};
-struct InputDeviceTraits : public DeviceTraits {};
-struct OutputFlagTraits
-{
-    typedef audio_output_flags_t Type;
-    typedef Vector<Type> Collection;
-};
-struct InputFlagTraits
-{
-    typedef audio_input_flags_t Type;
-    typedef Vector<Type> Collection;
-};
-struct FormatTraits
-{
-    typedef audio_format_t Type;
-    typedef Vector<Type> Collection;
-};
-struct ChannelTraits
-{
-    typedef audio_channel_mask_t Type;
-    typedef SortedVector<Type> Collection;
-};
-struct OutputChannelTraits : public ChannelTraits {};
-struct InputChannelTraits : public ChannelTraits {};
-struct ChannelIndexTraits : public ChannelTraits {};
-struct GainModeTraits
-{
-    typedef audio_gain_mode_t Type;
-    typedef Vector<Type> Collection;
-};
-struct StreamTraits
-{
-    typedef audio_stream_type_t Type;
-    typedef Vector<Type> Collection;
-};
-struct AudioModeTraits
-{
-    typedef audio_mode_t Type;
-    typedef Vector<Type> Collection;
-};
-struct AudioContentTraits
-{
-    typedef audio_content_type_t Type;
-    typedef Vector<Type> Collection;
-};
-struct UsageTraits
-{
-    typedef audio_usage_t Type;
-    typedef Vector<Type> Collection;
-};
-struct SourceTraits
-{
-    typedef audio_source_t Type;
-    typedef Vector<Type> Collection;
-};
 template <typename T>
 struct DefaultTraits
 {
     typedef T Type;
-    typedef Vector<Type> Collection;
+    typedef std::vector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.push_back(value);
+    }
 };
+template <typename T>
+struct VectorTraits
+{
+    typedef T Type;
+    typedef Vector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.add(value);
+    }
+};
+template <typename T>
+struct SortedVectorTraits
+{
+    typedef T Type;
+    typedef SortedVector<Type> Collection;
+    static void add(Collection &collection, Type value)
+    {
+        collection.add(value);
+    }
+};
+
+using SampleRateTraits = SortedVectorTraits<uint32_t>;
+using DeviceTraits = DefaultTraits<audio_devices_t>;
+struct OutputDeviceTraits : public DeviceTraits {};
+struct InputDeviceTraits : public DeviceTraits {};
+using ChannelTraits = SortedVectorTraits<audio_channel_mask_t>;
+struct OutputChannelTraits : public ChannelTraits {};
+struct InputChannelTraits : public ChannelTraits {};
+struct ChannelIndexTraits : public ChannelTraits {};
+using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
+using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
+using FormatTraits = VectorTraits<audio_format_t>;
+using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
+using StreamTraits = DefaultTraits<audio_stream_type_t>;
+using AudioModeTraits = DefaultTraits<audio_mode_t>;
+using AudioContentTraits = DefaultTraits<audio_content_type_t>;
+using UsageTraits = DefaultTraits<audio_usage_t>;
+using SourceTraits = DefaultTraits<audio_source_t>;
+struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
 
 template <class Traits>
 static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
@@ -110,7 +89,7 @@
     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
         typename Traits::Type value;
         if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
-            collection.add(value);
+            Traits::add(collection, value);
         }
     }
     free(literal);
@@ -181,7 +160,7 @@
     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
         typename Traits::Type value;
         if (fromString(cstr, value)) {
-            collection.add(value);
+            Traits::add(collection, value);
         }
     }
     free(literal);
@@ -234,6 +213,7 @@
 typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
 typedef TypeConverter<UsageTraits> UsageTypeConverter;
 typedef TypeConverter<SourceTraits> SourceTypeConverter;
+typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
 
 template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
 template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
@@ -249,6 +229,7 @@
 template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
 template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
 template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
+template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
 
 bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
 
@@ -274,6 +255,69 @@
 OutputChannelTraits::Collection outputChannelMasksFromString(
         const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
 
+static inline std::string toString(audio_usage_t usage)
+{
+    std::string usageLiteral;
+    if (!android::UsageTypeConverter::toString(usage, usageLiteral)) {
+        ALOGV("failed to convert usage: %d", usage);
+        return "AUDIO_USAGE_UNKNOWN";
+    }
+    return usageLiteral;
+}
+
+static inline std::string toString(audio_content_type_t content)
+{
+    std::string contentLiteral;
+    if (!android::AudioContentTypeConverter::toString(content, contentLiteral)) {
+        ALOGV("failed to convert content type: %d", content);
+        return "AUDIO_CONTENT_TYPE_UNKNOWN";
+    }
+    return contentLiteral;
+}
+
+static inline std::string toString(audio_stream_type_t stream)
+{
+    std::string streamLiteral;
+    if (!android::StreamTypeConverter::toString(stream, streamLiteral)) {
+        ALOGV("failed to convert stream: %d", stream);
+        return "AUDIO_STREAM_DEFAULT";
+    }
+    return streamLiteral;
+}
+
+static inline std::string toString(audio_source_t source)
+{
+    std::string sourceLiteral;
+    if (!android::SourceTypeConverter::toString(source, sourceLiteral)) {
+        ALOGV("failed to convert source: %d", source);
+        return "AUDIO_SOURCE_DEFAULT";
+    }
+    return sourceLiteral;
+}
+
+static inline std::string toString(const audio_attributes_t &attributes)
+{
+    std::ostringstream result;
+    result << "{ Content type: " << toString(attributes.content_type)
+           << " Usage: " << toString(attributes.usage)
+           << " Source: " << toString(attributes.source)
+           << " Flags: " << attributes.flags
+           << " Tags: " << attributes.tags
+           << " }";
+
+    return result.str();
+}
+
+static inline std::string toString(audio_mode_t mode)
+{
+    std::string modeLiteral;
+    if (!android::AudioModeConverter::toString(mode, modeLiteral)) {
+        ALOGV("failed to convert mode: %d", mode);
+        return "AUDIO_MODE_INVALID";
+    }
+    return modeLiteral;
+}
+
 }; // namespace android
 
 #endif  /*ANDROID_TYPE_CONVERTER_H_*/
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 6f2b35f..1aa1e13 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -14,6 +14,15 @@
         "-Wall",
     ],
 
+    static: {
+        cflags: [
+            "-Wno-multichar",
+            "-Werror",
+            "-Wall",
+            "-DNO_IMEMORY",
+        ],
+    },
+
     shared_libs: [
         "libbinder",
         "libstagefright_foundation",
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
index 26d0bd4..bab3a03 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -51,9 +51,12 @@
       mRangeLength(size),
       mOwnsData(true),
       mMetaData(new MetaDataBase) {
+#ifndef NO_IMEMORY
     if (size < kSharedMemThreshold
             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
+#endif
         mData = malloc(size);
+#ifndef NO_IMEMORY
     } else {
         ALOGV("creating memoryDealer");
         sp<MemoryDealer> memoryDealer =
@@ -71,6 +74,7 @@
             ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
         }
     }
+#endif
 }
 
 MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
diff --git a/media/libmediaextractor/MediaBufferGroup.cpp b/media/libmediaextractor/MediaBufferGroup.cpp
index 4e6beca..e88ed5a 100644
--- a/media/libmediaextractor/MediaBufferGroup.cpp
+++ b/media/libmediaextractor/MediaBufferGroup.cpp
@@ -62,6 +62,7 @@
         mInternal->mGrowthLimit = buffers;
     }
 
+#ifndef NO_IMEMORY
     if (buffer_size >= kSharedMemoryThreshold) {
         ALOGD("creating MemoryDealer");
         // Using a single MemoryDealer is efficient for a group of shared memory objects.
@@ -84,6 +85,9 @@
         }
         return;
     }
+#else
+    (void)kSharedMemoryThreshold;
+#endif
 
     // Non-shared memory allocation.
     for (size_t i = 0; i < buffers; ++i) {
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index 5b362a4..ace63ae 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -46,12 +46,13 @@
     explicit MediaBuffer(size_t size);
 
     explicit MediaBuffer(const sp<ABuffer> &buffer);
-
+#ifndef NO_IMEMORY
     MediaBuffer(const sp<IMemory> &mem) :
         MediaBuffer((uint8_t *)mem->pointer() + sizeof(SharedControl), mem->size()) {
         // delegate and override mMemory
         mMemory = mem;
     }
+#endif
 
     // If MediaBufferGroup is set, decrement the local reference count;
     // if the local reference count drops to 0, return the buffer to the
@@ -92,17 +93,26 @@
     }
 
     virtual int remoteRefcount() const {
+#ifndef NO_IMEMORY
         if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
         int32_t remoteRefcount =
                 reinterpret_cast<SharedControl *>(mMemory->pointer())->getRemoteRefcount();
         // Sanity check so that remoteRefCount() is non-negative.
         return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
+#else
+        return 0;
+#endif
     }
 
     // returns old value
     int addRemoteRefcount(int32_t value) {
+#ifndef NO_IMEMORY
         if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
         return reinterpret_cast<SharedControl *>(mMemory->pointer())->addRemoteRefcount(value);
+#else
+        (void) value;
+        return 0;
+#endif
     }
 
     bool isDeadObject() const {
@@ -110,8 +120,13 @@
     }
 
     static bool isDeadObject(const sp<IMemory> &memory) {
+#ifndef NO_IMEMORY
         if (memory.get() == nullptr || memory->pointer() == nullptr) return false;
         return reinterpret_cast<SharedControl *>(memory->pointer())->isDeadObject();
+#else
+        (void) memory;
+        return false;
+#endif
     }
 
     // Sticky on enabling of shared memory MediaBuffers. By default we don't use
@@ -204,7 +219,11 @@
     };
 
     inline SharedControl *getSharedControl() const {
+#ifndef NO_IMEMORY
          return reinterpret_cast<SharedControl *>(mMemory->pointer());
+#else
+         return nullptr;
+#endif
      }
 };
 
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
index eb49f4c..3682368 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
@@ -96,6 +96,14 @@
             return ((MediaBufferBase*)handle)->size();
         };
 
+        mWrapper->range_offset = [](void *handle) -> size_t {
+            return ((MediaBufferBase*)handle)->range_offset();
+        };
+
+        mWrapper->range_length = [](void *handle) -> size_t {
+            return ((MediaBufferBase*)handle)->range_length();
+        };
+
         mWrapper->set_range = [](void *handle, size_t offset, size_t length) -> void {
             return ((MediaBufferBase*)handle)->set_range(offset, length);
         };
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index c7cd7d2..a945ffd 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -86,7 +86,7 @@
                     MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC);
             status_t        notifyAt(int64_t mediaTimeUs);
             status_t        getCurrentPosition(int64_t *msec);
-            status_t        getDuration(int64_t *msec);
+            status_t        getDuration(int64_t srcId, int64_t *msec);
             status_t        reset();
             status_t        setAudioStreamType(audio_stream_type_t type);
             status_t        getAudioStreamType(audio_stream_type_t *type);
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index 2ae5a8c..f432059 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -718,8 +718,15 @@
     return ret;
 }
 
-status_t MediaPlayer2::getDuration(int64_t *msec) {
+status_t MediaPlayer2::getDuration(int64_t srcId, int64_t *msec) {
     Mutex::Autolock _l(mLock);
+    // TODO: cache duration for currentSrcId and nextSrcId, and return correct
+    // value for nextSrcId.
+    if (srcId != mSrcId) {
+        *msec = -1;
+        return OK;
+    }
+
     ALOGV("getDuration_l");
     bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
             MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 81ffbc7..080d923 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -791,9 +791,13 @@
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
+            int64_t srcId;
+            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
+
             PlayerMessage* reply;
             CHECK(msg->findPointer("reply", (void**)&reply));
 
+            // TODO: use correct source info based on srcId.
             size_t inbandTracks = 0;
             if (mCurrentSourceInfo.mSource != NULL) {
                 inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
@@ -824,10 +828,14 @@
 
         case kWhatGetSelectedTrack:
         {
+            int64_t srcId;
+            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
+
             int32_t type32;
             CHECK(msg->findInt32("type", (int32_t*)&type32));
             media_track_type type = (media_track_type)type32;
 
+            // TODO: use correct source info based on srcId.
             size_t inbandTracks = 0;
             status_t err = INVALID_OPERATION;
             ssize_t selectedTrack = -1;
@@ -863,15 +871,18 @@
             sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
+            int64_t srcId;
             size_t trackIndex;
             int32_t select;
             int64_t timeUs;
+            CHECK(msg->findInt64("srcId", (int64_t*)&srcId));
             CHECK(msg->findSize("trackIndex", &trackIndex));
             CHECK(msg->findInt32("select", &select));
             CHECK(msg->findInt64("timeUs", &timeUs));
 
             status_t err = INVALID_OPERATION;
 
+            // TODO: use correct source info based on srcId.
             size_t inbandTracks = 0;
             if (mCurrentSourceInfo.mSource != NULL) {
                 inbandTracks = mCurrentSourceInfo.mSource->getTrackCount();
@@ -2324,8 +2335,9 @@
     return OK;
 }
 
-status_t NuPlayer2::getTrackInfo(PlayerMessage* reply) const {
+status_t NuPlayer2::getTrackInfo(int64_t srcId, PlayerMessage* reply) const {
     sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
+    msg->setInt64("srcId", srcId);
     msg->setPointer("reply", reply);
 
     sp<AMessage> response;
@@ -2333,9 +2345,10 @@
     return err;
 }
 
-status_t NuPlayer2::getSelectedTrack(int32_t type, PlayerMessage* reply) const {
+status_t NuPlayer2::getSelectedTrack(int64_t srcId, int32_t type, PlayerMessage* reply) const {
     sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
     msg->setPointer("reply", reply);
+    msg->setInt64("srcId", srcId);
     msg->setInt32("type", type);
 
     sp<AMessage> response;
@@ -2346,8 +2359,9 @@
     return err;
 }
 
-status_t NuPlayer2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
+status_t NuPlayer2::selectTrack(int64_t srcId, size_t trackIndex, bool select, int64_t timeUs) {
     sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
+    msg->setInt64("srcId", srcId);
     msg->setSize("trackIndex", trackIndex);
     msg->setInt32("select", select);
     msg->setInt64("timeUs", timeUs);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index e9b5f11..fdc128f 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -82,9 +82,9 @@
     void rewind();
 
     status_t setVideoScalingMode(int32_t mode);
-    status_t getTrackInfo(PlayerMessage* reply) const;
-    status_t getSelectedTrack(int32_t type, PlayerMessage* reply) const;
-    status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
+    status_t getTrackInfo(int64_t srcId, PlayerMessage* reply) const;
+    status_t getSelectedTrack(int64_t srcId, int32_t type, PlayerMessage* reply) const;
+    status_t selectTrack(int64_t srcId, size_t trackIndex, bool select, int64_t timeUs);
     status_t getCurrentPosition(int64_t *mediaUs);
     void getStats(Vector<sp<AMessage> > *mTrackStats);
 
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 56d708a..2dab2dd 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -603,28 +603,33 @@
 
         case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
         {
-            return mPlayer->getTrackInfo(response);
+            int64_t srcId = (it++)->int64_value();
+            return mPlayer->getTrackInfo(srcId, response);
         }
 
         case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
         {
+            int64_t srcId = (it++)->int64_value();
             int trackIndex = (it++)->int32_value();
             int64_t msec = 0;
             // getCurrentPosition should always return OK
             getCurrentPosition(&msec);
-            return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000LL);
+            return mPlayer->selectTrack(srcId, trackIndex, true /* select */, msec * 1000LL);
         }
 
         case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
         {
+            int64_t srcId = (it++)->int64_value();
             int trackIndex = (it++)->int32_value();
-            return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
+            return mPlayer->selectTrack(
+                    srcId, trackIndex, false /* select */, 0xdeadbeef /* not used */);
         }
 
         case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
         {
+            int64_t srcId = (it++)->int64_value();
             int32_t type = (it++)->int32_value();
-            return mPlayer->getSelectedTrack(type, response);
+            return mPlayer->getSelectedTrack(srcId, type, response);
         }
 
         default:
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 9aea88a..dec5d3b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -77,7 +77,7 @@
     },
 }
 
-cc_library_shared {
+cc_library {
     name: "libstagefright",
 
     srcs: [
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6ff3d78..a48466a 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3674,6 +3674,29 @@
         TRESPASS();
     }
     mOwner->beginBox(fourcc);    // TextMetaDataSampleEntry
+
+    //  HACK to make the metadata track compliant with the ISO standard.
+    //
+    //  Metadata track is added from API 26 and the original implementation does not
+    //  fully followed the TextMetaDataSampleEntry specified in ISO/IEC 14496-12-2015
+    //  in that only the mime_format is written out. content_encoding and
+    //  data_reference_index have not been written out. This leads to the failure
+    //  when some MP4 parser tries to parse the metadata track according to the
+    //  standard. The hack here will make the metadata track compliant with the
+    //  standard while still maintaining backwards compatibility. This would enable
+    //  Android versions before API 29 to be able to read out the standard compliant
+    //  Metadata track generated with Android API 29 and upward. The trick is based
+    //  on the fact that the Metadata track must start with prefix “application/” and
+    //  those missing fields are not used in Android's Metadata track. By writting
+    //  out the mime_format twice, the first mime_format will be used to fill out the
+    //  missing reserved, data_reference_index and content encoding fields. On the
+    //  parser side, the extracter before API 29  will read out the first mime_format
+    //  correctly and drop the second mime_format. The extractor from API 29 will
+    //  check if the reserved, data_reference_index and content encoding are filled
+    //  with “application” to detect if this is a standard compliant metadata track
+    //  and read out the data accordingly.
+    mOwner->writeCString(mime);
+
     mOwner->writeCString(mime);  // metadata mime_format
     mOwner->endBox(); // mett
 }
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 6c0f989..1e49f6a 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -16,6 +16,7 @@
 
 #include <mutex>
 
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/Utils.h>
 
@@ -216,10 +217,58 @@
         if (format->mFormat->findInt64("timeUs", &val64)) {
             meta.setInt64(kKeyTime, val64);
         }
+        if (format->mFormat->findInt64("duration", &val64)) {
+            meta.setInt64(kKeyDuration, val64);
+        }
+        if (format->mFormat->findInt64("target-time", &val64)) {
+            meta.setInt64(kKeyTargetTime, val64);
+        }
         int32_t val32;
         if (format->mFormat->findInt32("is-sync-frame", &val32)) {
             meta.setInt32(kKeyIsSyncFrame, val32);
         }
+        if (format->mFormat->findInt32("temporal-layer-id", &val32)) {
+            meta.setInt32(kKeyTemporalLayerId, val32);
+        }
+        if (format->mFormat->findInt32("temporal-layer-count", &val32)) {
+            meta.setInt32(kKeyTemporalLayerCount, val32);
+        }
+        if (format->mFormat->findInt32("crypto-default-iv-size", &val32)) {
+            meta.setInt32(kKeyCryptoDefaultIVSize, val32);
+        }
+        if (format->mFormat->findInt32("crypto-mode", &val32)) {
+            meta.setInt32(kKeyCryptoMode, val32);
+        }
+        if (format->mFormat->findInt32("crypto-encrypted-byte-block", &val32)) {
+            meta.setInt32(kKeyEncryptedByteBlock, val32);
+        }
+        if (format->mFormat->findInt32("crypto-skip-byte-block", &val32)) {
+            meta.setInt32(kKeySkipByteBlock, val32);
+        }
+        if (format->mFormat->findInt32("valid-samples", &val32)) {
+            meta.setInt32(kKeyValidSamples, val32);
+        }
+        sp<ABuffer> valbuf;
+        if (format->mFormat->findBuffer("crypto-plain-sizes", &valbuf)) {
+            meta.setData(kKeyPlainSizes,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
+        if (format->mFormat->findBuffer("crypto-encrypted-sizes", &valbuf)) {
+            meta.setData(kKeyEncryptedSizes,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
+        if (format->mFormat->findBuffer("crypto-key", &valbuf)) {
+            meta.setData(kKeyCryptoKey,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
+        if (format->mFormat->findBuffer("crypto-iv", &valbuf)) {
+            meta.setData(kKeyCryptoIV,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
+        if (format->mFormat->findBuffer("sei", &valbuf)) {
+            meta.setData(kKeySEI,
+                    MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+        }
     } else {
         *buffer = nullptr;
     }
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 670b607..8f2427e 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -598,7 +598,10 @@
     {
         { "exif-offset", kKeyExifOffset },
         { "exif-size", kKeyExifSize },
+        { "target-time", kKeyTargetTime },
         { "thumbnail-time", kKeyThumbnailTime },
+        { "timeUs", kKeyTime },
+        { "durationUs", kKeyDuration },
     }
 };
 
@@ -610,12 +613,14 @@
         { "crypto-default-iv-size", kKeyCryptoDefaultIVSize },
         { "crypto-encrypted-byte-block", kKeyEncryptedByteBlock },
         { "crypto-skip-byte-block", kKeySkipByteBlock },
+        { "frame-count", kKeyFrameCount },
         { "max-bitrate", kKeyMaxBitRate },
         { "pcm-big-endian", kKeyPcmBigEndian },
         { "temporal-layer-count", kKeyTemporalLayerCount },
+        { "temporal-layer-id", kKeyTemporalLayerId },
         { "thumbnail-width", kKeyThumbnailWidth },
         { "thumbnail-height", kKeyThumbnailHeight },
-        { "frame-count", kKeyFrameCount },
+        { "valid-samples", kKeyValidSamples },
     }
 };
 
@@ -626,7 +631,10 @@
         { "pssh", kKeyPssh },
         { "crypto-iv", kKeyCryptoIV },
         { "crypto-key", kKeyCryptoKey },
+        { "crypto-encrypted-sizes", kKeyEncryptedSizes },
+        { "crypto-plain-sizes", kKeyPlainSizes },
         { "icc-profile", kKeyIccProfile },
+        { "sei", kKeySEI },
         { "text-format-data", kKeyTextFormatData },
     }
 };
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index 78d410a..c4a072b 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -29,7 +29,6 @@
 
     shared_libs: [
         "liblog",
-        "libbinder",
         "libcrypto",
         "libcutils",
         "libmedia",
@@ -38,10 +37,11 @@
         "libstagefright",
         "libstagefright_foundation",
         "libutils",
-        "libhidlallocatorutils",
         "libhidlbase",
+        "libhidlmemory",
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
+        "android.hidl.allocator@1.0",
     ],
 
     header_libs: [
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 590131e..e9baa1a 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -23,10 +23,10 @@
 #include "ESQueue.h"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
-#include <binder/IMemory.h>
-#include <binder/MemoryDealer.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
 #include <cutils/native_handle.h>
-#include <hidlmemory/FrameworkUtils.h>
+#include <hidlmemory/mapping.h>
 #include <media/cas/DescramblerAPI.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -46,12 +46,13 @@
 #include <inttypes.h>
 
 namespace android {
-using hardware::fromHeap;
 using hardware::hidl_string;
 using hardware::hidl_vec;
-using hardware::HidlMemory;
+using hardware::hidl_memory;
 using namespace hardware::cas::V1_0;
 using namespace hardware::cas::native::V1_0;
+typedef hidl::allocator::V1_0::IAllocator TAllocator;
+typedef hidl::memory::V1_0::IMemory TMemory;
 
 // I want the expression "y" evaluated even if verbose logging is off.
 #define MY_LOGV(x, y) \
@@ -208,9 +209,8 @@
     bool mScrambled;
     bool mSampleEncrypted;
     sp<AMessage> mSampleAesKeyItem;
-    sp<IMemory> mMem;
-    sp<MemoryDealer> mDealer;
-    sp<HidlMemory> mHidlMemory;
+    sp<TMemory> mHidlMemory;
+    sp<TAllocator> mHidlAllocator;
     hardware::cas::native::V1_0::SharedBuffer mDescramblerSrcBuffer;
     sp<ABuffer> mDescrambledBuffer;
     List<SubSampleInfo> mSubSamples;
@@ -975,16 +975,43 @@
             mBuffer == NULL ? 0 : mBuffer->capacity(), neededSize, mScrambled);
 
     sp<ABuffer> newBuffer, newScrambledBuffer;
-    sp<IMemory> newMem;
-    sp<MemoryDealer> newDealer;
+    sp<TMemory> newMem;
     if (mScrambled) {
-        size_t alignment = MemoryDealer::getAllocationAlignment();
-        neededSize = (neededSize + (alignment - 1)) & ~(alignment - 1);
-        // Align to multiples of 64K.
-        neededSize = (neededSize + 65535) & ~65535;
-        newDealer = new MemoryDealer(neededSize, "ATSParser");
-        newMem = newDealer->allocate(neededSize);
-        newScrambledBuffer = new ABuffer(newMem->pointer(), newMem->size());
+        if (mHidlAllocator == nullptr) {
+            mHidlAllocator = TAllocator::getService("ashmem");
+            if (mHidlAllocator == nullptr) {
+                ALOGE("[stream %d] can't get hidl allocator", mElementaryPID);
+                return false;
+            }
+        }
+
+        hidl_memory hidlMemToken;
+        bool success;
+        auto transStatus = mHidlAllocator->allocate(
+                neededSize,
+                [&success, &hidlMemToken](
+                        bool s,
+                        hidl_memory const& m) {
+                    success = s;
+                    hidlMemToken = m;
+                });
+
+        if (!transStatus.isOk()) {
+            ALOGE("[stream %d] hidl allocator failed at the transport: %s",
+                    mElementaryPID, transStatus.description().c_str());
+            return false;
+        }
+        if (!success) {
+            ALOGE("[stream %d] hidl allocator failed", mElementaryPID);
+            return false;
+        }
+        newMem = mapMemory(hidlMemToken);
+        if (newMem == nullptr || newMem->getPointer() == nullptr) {
+            ALOGE("[stream %d] hidl failed to map memory", mElementaryPID);
+            return false;
+        }
+
+        newScrambledBuffer = new ABuffer(newMem->getPointer(), newMem->getSize());
 
         if (mDescrambledBuffer != NULL) {
             memcpy(newScrambledBuffer->data(),
@@ -993,24 +1020,15 @@
         } else {
             newScrambledBuffer->setRange(0, 0);
         }
-        mMem = newMem;
-        mDealer = newDealer;
+        mHidlMemory = newMem;
         mDescrambledBuffer = newScrambledBuffer;
 
-        ssize_t offset;
-        size_t size;
-        sp<IMemoryHeap> heap = newMem->getMemory(&offset, &size);
-        if (heap == NULL) {
-            return false;
-        }
+        mDescramblerSrcBuffer.heapBase = hidlMemToken;
+        mDescramblerSrcBuffer.offset = 0ULL;
+        mDescramblerSrcBuffer.size =  (uint64_t)neededSize;
 
-        mHidlMemory = fromHeap(heap);
-        mDescramblerSrcBuffer.heapBase = *mHidlMemory;
-        mDescramblerSrcBuffer.offset = (uint64_t) offset;
-        mDescramblerSrcBuffer.size = (uint64_t) size;
-
-        ALOGD("[stream %d] created shared buffer for descrambling, offset %zd, size %zu",
-                mElementaryPID, offset, size);
+        ALOGD("[stream %d] created shared buffer for descrambling, size %zu",
+                mElementaryPID, neededSize);
     } else {
         // Align to multiples of 64K.
         neededSize = (neededSize + 65535) & ~65535;
@@ -1498,7 +1516,7 @@
         return UNKNOWN_ERROR;
     }
 
-    if (mDescrambledBuffer == NULL || mMem == NULL) {
+    if (mDescrambledBuffer == NULL || mHidlMemory == NULL) {
         ALOGE("received scrambled packets without shared memory!");
 
         return UNKNOWN_ERROR;
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index e516cf1..a507b91 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -30,9 +30,10 @@
     shared_libs: [
         "libcrypto",
         "libmedia",
-        "libhidlallocatorutils",
+        "libhidlmemory",
         "android.hardware.cas.native@1.0",
         "android.hidl.memory@1.0",
+        "android.hidl.allocator@1.0",
     ],
 
     header_libs: [
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index e0af80d..92d3aef 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -294,9 +294,11 @@
 EXPORT const char* AMEDIAFORMAT_KEY_COMPOSER = "composer";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE = "crypto-default-iv-size";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK = "crypto-encrypted-byte-block";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES = "crypto-encrypted-sizes";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-encrypted-sizes";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
@@ -361,6 +363,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_SEI = "sei";
 EXPORT const char* AMEDIAFORMAT_KEY_SLICE_HEIGHT = "slice-height";
 EXPORT const char* AMEDIAFORMAT_KEY_STRIDE = "stride";
+EXPORT const char* AMEDIAFORMAT_KEY_TARGET_TIME = "target-time";
 EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT = "temporal-layer-count";
 EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
 EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
@@ -374,6 +377,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_TITLE = "title";
 EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
 EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
+EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
 EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
 EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
 
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 2cd1d04..2551228 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -190,9 +190,11 @@
 extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_IV __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_KEY __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_MODE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CSD_AVC __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CSD_HEVC __INTRODUCED_IN(29);
@@ -217,12 +219,14 @@
 extern const char* AMEDIAFORMAT_KEY_PSSH __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_SAR_HEIGHT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_SAR_WIDTH __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_TARGET_TIME __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_TITLE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_VALID_SAMPLES __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);
 
 #endif /* __ANDROID_API__ >= 29 */
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 3567899..c50084e 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -58,9 +58,11 @@
     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_ENCRYPTED_SIZES; # 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_PLAIN_SIZES; # 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
@@ -124,6 +126,7 @@
     AMEDIAFORMAT_KEY_SEI; # var introduced=28
     AMEDIAFORMAT_KEY_SLICE_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_STRIDE; # var introduced=21
+    AMEDIAFORMAT_KEY_TARGET_TIME; # var introduced=29
     AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT; # var introduced=29
     AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID; # var introduced=28
     AMEDIAFORMAT_KEY_TEMPORAL_LAYERING; # var introduced=28
@@ -137,6 +140,7 @@
     AMEDIAFORMAT_KEY_TIME_US; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_INDEX; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
+    AMEDIAFORMAT_KEY_VALID_SAMPLES; # var introduced=29
     AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
     AMEDIAFORMAT_KEY_YEAR; # var introduced=29
     AMediaCodecActionCode_isRecoverable; # introduced=28
diff --git a/packages/MediaComponents/apex/java/android/media/MediaMetadata.java b/packages/MediaComponents/apex/java/android/media/MediaMetadata.java
index 33e6916..adfd20b 100644
--- a/packages/MediaComponents/apex/java/android/media/MediaMetadata.java
+++ b/packages/MediaComponents/apex/java/android/media/MediaMetadata.java
@@ -422,9 +422,7 @@
     }
 
     private MediaMetadata(Parcel in) {
-        //TODO(b/119789387): Resolve hidden API usage: Bundle#setDefusable
-        //mBundle = Bundle.setDefusable(in.readBundle(), true);
-        mBundle = new Bundle();  //TODO:remove this.
+        mBundle = in.readBundle();
     }
 
     /**
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISession.aidl b/packages/MediaComponents/apex/java/android/media/session/ISession.aidl
index c5b376c..14b1c64 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISession.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISession.aidl
@@ -39,7 +39,7 @@
     void destroy();
 
     // These commands are for the TransportPerformer
-    void setMetadata(in MediaMetadata metadata);
+    void setMetadata(in MediaMetadata metadata, long duration, String metadataDescription);
     void setPlaybackState(in PlaybackState state);
     void setQueue(in MediaParceledListSlice queue);
     void setQueueTitle(CharSequence title);
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index e5eff95..943843d 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -30,6 +30,7 @@
 import android.media.MediaParceledListSlice;
 import android.media.Rating;
 import android.media.VolumeProvider;
+import android.media.session.MediaSessionManager.RemoteUserInfo;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -40,7 +41,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
 import android.util.Log;
@@ -439,11 +439,21 @@
      * @see android.media.MediaMetadata.Builder#putBitmap
      */
     public void setMetadata(@Nullable MediaMetadata metadata) {
+        long duration = -1;
+        int fields = 0;
+        MediaDescription description = null;
         if (metadata != null) {
             metadata = (new MediaMetadata.Builder(metadata, mMaxBitmapSize)).build();
+            if (metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+                duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+            }
+            fields = metadata.size();
+            description = metadata.getDescription();
         }
+        String metadataDescription = "size=" + fields + ", description=" + description;
+
         try {
-            mBinder.setMetadata(metadata);
+            mBinder.setMetadata(metadata, duration, metadataDescription);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Dead object in setPlaybackState.", e);
         }
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 02ab8ad..bfa1b5e 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -25,7 +25,11 @@
     libmedia_helper \
     libmediametrics \
     libmediautils \
-    libeffectsconfig
+    libeffectsconfig \
+    libsensorprivacy
+
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
+    libsensorprivacy
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index ebb9352..bb9cad8 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -116,6 +116,7 @@
     audio_module_handle_t getModuleHandle() const;
     uint32_t getModuleVersionMajor() const;
     const char *getModuleName() const;
+    sp<HwModule> getModule() const { return mModule; }
 
     bool useInputChannelMask() const
     {
@@ -137,12 +138,12 @@
     void log(const char* indent) const;
 
     AudioGainCollection mGains; // gain controllers
-    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
 
 private:
     void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
     void pickSamplingRate(uint32_t &rate,const SampleRateVector &samplingRates) const;
 
+    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
     String8  mName;
     audio_port_type_t mType;
     audio_port_role_t mRole;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
index 330f1d4..0357ff4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioRoute.h
@@ -46,6 +46,19 @@
 
     audio_route_type_t getType() const { return mType; }
 
+    /**
+     * @brief supportsPatch checks if an audio patch is supported by a Route declared in
+     * the audio_policy_configuration.xml file.
+     * If the patch is supported natively by an AudioHAL (which supports of course Routing API 3.0),
+     * audiopolicy will not request AudioFlinger to use a software bridge to realize a patch
+     * between 2 ports.
+     * @param srcPort (aka the source) to be considered
+     * @param dstPort (aka the sink) to be considered
+     * @return true if the audio route supports the connection between the sink and the source,
+     * false otherwise
+     */
+    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
     void dump(String8 *dst, int spaces) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 6f99bf3..d02123c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -39,6 +39,8 @@
     virtual const String8 getTagName() const { return mTagName; }
 
     audio_devices_t type() const { return mDeviceType; }
+    String8 address() const { return mAddress; }
+    void setAddress(const String8 &address) { mAddress = address; }
 
     const FormatVector& encodedFormats() const { return mEncodedFormats; }
 
@@ -57,39 +59,113 @@
     audio_port_handle_t getId() const;
     void dump(String8 *dst, int spaces, int index, bool verbose = true) const;
     void log() const;
-
-    String8 mAddress;
+    std::string toString() const;
 
 private:
+    String8 mAddress{""};
     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;
+    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
 };
 
 class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
 {
 public:
     DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
+    explicit DeviceVector(const sp<DeviceDescriptor>& item) : DeviceVector()
+    {
+        add(item);
+    }
 
     ssize_t add(const sp<DeviceDescriptor>& item);
     void add(const DeviceVector &devices);
     ssize_t remove(const sp<DeviceDescriptor>& item);
+    void remove(const DeviceVector &devices);
     ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
 
     audio_devices_t types() const { return mDeviceTypes; }
 
     // If 'address' is empty, a device with a non-empty address may be returned
     // if there is no device with the specified 'type' and empty address.
-    sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address) const;
+    sp<DeviceDescriptor> getDevice(audio_devices_t type, const String8 &address = {}) const;
     DeviceVector getDevicesFromTypeMask(audio_devices_t types) const;
+
+    /**
+     * @brief getDeviceFromId
+     * @param id of the DeviceDescriptor to seach (aka Port handle).
+     * @return DeviceDescriptor associated to port id if found, nullptr otherwise. If the id is
+     * equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
+     */
     sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
     sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
     DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
     audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
 
+    bool contains(const sp<DeviceDescriptor>& item) const { return indexOf(item) >= 0; }
+
+    /**
+     * @brief containsAtLeastOne
+     * @param devices vector of devices to check against.
+     * @return true if the DeviceVector contains at list one of the devices from the given vector.
+     */
+    bool containsAtLeastOne(const DeviceVector &devices) const;
+
+    /**
+     * @brief containsAllDevices
+     * @param devices vector of devices to check against.
+     * @return true if the DeviceVector contains all the devices from the given vector
+     */
+    bool containsAllDevices(const DeviceVector &devices) const;
+
+    /**
+     * @brief filter the devices supported by this collection against another collection
+     * @param devices to filter against
+     * @return
+     */
+    DeviceVector filter(const DeviceVector &devices) const;
+
+    /**
+     * @brief merge two vectors. As SortedVector Implementation is buggy (it does not check the size
+     * of the destination vector, only of the source, it provides a safe implementation
+     * @param devices source device vector to merge with
+     * @return size of the merged vector.
+     */
+    ssize_t merge(const DeviceVector &devices)
+    {
+        if (isEmpty()) {
+            add(devices);
+            return size();
+        }
+        return SortedVector::merge(devices);
+    }
+
+    /**
+     * @brief operator == DeviceVector are equals if all the DeviceDescriptor can be found (aka
+     * DeviceDescriptor with same type and address) and the vector has same size.
+     * @param right DeviceVector to compare to.
+     * @return true if right contains the same device and has the same size.
+     */
+    bool operator==(const DeviceVector &right) const
+    {
+        if (size() != right.size()) {
+            return false;
+        }
+        for (const auto &device : *this) {
+            if (right.indexOf(device) < 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    bool operator!=(const DeviceVector &right) const
+    {
+        return !operator==(right);
+    }
+
+    std::string toString() const;
+
     void dump(String8 *dst, const String8 &tag, int spaces = 0, bool verbose = true) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 6560431..2b57fa9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -81,6 +81,17 @@
         return mPorts.findByTagName(tagName);
     }
 
+    /**
+     * @brief supportsPatch checks if an audio patch between 2 ports beloging to this HwModule
+     * is supported by a HwModule. The ports and the route shall be declared in the
+     * audio_policy_configuration.xml file.
+     * @param srcPort (aka the source) to be considered
+     * @param dstPort (aka the sink) to be considered
+     * @return true if the HwModule supports the connection between the sink and the source,
+     * false otherwise
+     */
+    bool supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const;
+
     // TODO remove from here (split serialization)
     void dump(String8 *dst) const;
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 8ff8238..ca6ca56 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -88,7 +88,7 @@
 
     bool supportDeviceAddress(const String8 &address) const
     {
-        return mSupportedDevices[0]->mAddress == address;
+        return mSupportedDevices[0]->address() == address;
     }
 
     // chose first device present in mSupportedDevices also part of deviceType
diff --git a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
index 63c19d1..6b0476c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -23,26 +23,10 @@
 
 namespace android {
 
-struct DeviceCategoryTraits
-{
-    typedef device_category Type;
-    typedef Vector<Type> Collection;
-};
-struct MixTypeTraits
-{
-    typedef int32_t Type;
-    typedef Vector<Type> Collection;
-};
-struct RouteFlagTraits
-{
-    typedef uint32_t Type;
-    typedef Vector<Type> Collection;
-};
-struct RuleTraits
-{
-    typedef uint32_t Type;
-    typedef Vector<Type> Collection;
-};
+struct RuleTraits : public DefaultTraits<uint32_t> {};
+using DeviceCategoryTraits = DefaultTraits<device_category>;
+struct MixTypeTraits : public DefaultTraits<int32_t> {};
+struct RouteFlagTraits : public DefaultTraits<uint32_t> {};
 
 typedef TypeConverter<DeviceCategoryTraits> DeviceCategoryConverter;
 typedef TypeConverter<MixTypeTraits> MixTypeConverter;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4ce6b08..97504ab 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -698,8 +698,8 @@
     sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
 
     if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
-        && (primaryOutput->mProfile->mModule != NULL)) {
-        sp<HwModule> primaryHwModule = primaryOutput->mProfile->mModule;
+        && (primaryOutput->mProfile->getModule() != NULL)) {
+        sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
         Vector <sp<IOProfile>> primaryHwModuleOutputProfiles =
                                    primaryHwModule->getOutputProfiles();
         for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index c1fe5b0..79f0919 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -37,4 +37,19 @@
     dst->append("\n");
 }
 
+bool AudioRoute::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const
+{
+    if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
+        return false;
+    }
+    ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+    for (const auto &sourcePort : mSources) {
+        if (sourcePort == srcPort) {
+            ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+            return true;
+        }
+    }
+    return false;
+}
+
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 9e5f944..04cbcd1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -35,7 +35,7 @@
     AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                              AUDIO_PORT_ROLE_SOURCE),
-    mAddress(""), mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats), mId(0)
+    mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
 {
     if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
         mAddress = String8("0");
@@ -132,6 +132,13 @@
     return ret;
 }
 
+void DeviceVector::remove(const DeviceVector &devices)
+{
+    for (const auto& device : devices) {
+        remove(device);
+    }
+}
+
 DeviceVector DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
 {
     DeviceVector devices;
@@ -159,9 +166,9 @@
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
         if (itemAt(i)->type() == type) {
-            if (address == "" || itemAt(i)->mAddress == address) {
+            if (address == "" || itemAt(i)->address() == address) {
                 device = itemAt(i);
-                if (itemAt(i)->mAddress == address) {
+                if (itemAt(i)->address() == address) {
                     break;
                 }
             }
@@ -174,9 +181,11 @@
 
 sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
 {
-    for (const auto& device : *this) {
-        if (device->getId() == id) {
-            return device;
+    if (id != AUDIO_PORT_HANDLE_NONE) {
+        for (const auto& device : *this) {
+            if (device->getId() == id) {
+                return device;
+            }
         }
     }
     return nullptr;
@@ -188,8 +197,8 @@
     bool isOutput = audio_is_output_devices(type);
     type &= ~AUDIO_DEVICE_BIT_IN;
     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
-        bool curIsOutput = audio_is_output_devices(itemAt(i)->mDeviceType);
-        audio_devices_t curType = itemAt(i)->mDeviceType & ~AUDIO_DEVICE_BIT_IN;
+        bool curIsOutput = audio_is_output_devices(itemAt(i)->type());
+        audio_devices_t curType = itemAt(i)->type() & ~AUDIO_DEVICE_BIT_IN;
         if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
             devices.add(itemAt(i));
             type &= ~curType;
@@ -251,8 +260,7 @@
     // without the test?
     // This has been demonstrated to NOT be true (at start up)
     // ALOG_ASSERT(mModule != NULL);
-    dstConfig->ext.device.hw_module =
-            mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
+    dstConfig->ext.device.hw_module = getModuleHandle();
     (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
 }
 
@@ -263,7 +271,7 @@
     port->id = mId;
     toAudioPortConfig(&port->active_config);
     port->ext.device.type = mDeviceType;
-    port->ext.device.hw_module = mModule->getHandle();
+    port->ext.device.hw_module = getModuleHandle();
     (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
 }
 
@@ -294,6 +302,49 @@
     AudioPort::dump(dst, spaces, verbose);
 }
 
+std::string DeviceDescriptor::toString() const
+{
+    std::stringstream sstream;
+    sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
+    return sstream.str();
+}
+
+std::string DeviceVector::toString() const
+{
+    if (isEmpty()) {
+        return {"AUDIO_DEVICE_NONE"};
+    }
+    std::string result = {"{"};
+    for (const auto &device : *this) {
+        if (device != *begin()) {
+           result += ";";
+        }
+        result += device->toString();
+    }
+    return result + "}";
+}
+
+DeviceVector DeviceVector::filter(const DeviceVector &devices) const
+{
+    DeviceVector filteredDevices;
+    for (const auto &device : *this) {
+        if (devices.contains(device)) {
+            filteredDevices.add(device);
+        }
+    }
+    return filteredDevices;
+}
+
+bool DeviceVector::containsAtLeastOne(const DeviceVector &devices) const
+{
+    return !filter(devices).isEmpty();
+}
+
+bool DeviceVector::containsAllDevices(const DeviceVector &devices) const
+{
+    return filter(devices).size() == devices.size();
+}
+
 void DeviceDescriptor::log() const
 {
     std::string device;
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 92bc595..80af88d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -51,7 +51,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     profile->addSupportedDevice(devDesc);
 
     return addOutputProfile(profile);
@@ -113,7 +113,7 @@
                                               config->sample_rate));
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     profile->addSupportedDevice(devDesc);
 
     ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
@@ -218,6 +218,15 @@
     mHandle = handle;
 }
 
+bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const {
+    for (const auto &route : mRoutes) {
+        if (route->supportsPatch(srcPort, dstPort)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void HwModule::dump(String8 *dst) const
 {
     dst->appendFormat("  - name: %s\n", getName());
@@ -287,7 +296,7 @@
 
     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
     devDesc->setName(String8(device_name));
-    devDesc->mAddress = address;
+    devDesc->setAddress(address);
     return devDesc;
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 179a678..1154654 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -516,7 +516,7 @@
     std::string address = getXmlAttribute(cur, Attributes::address);
     if (!address.empty()) {
         ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
-        deviceDesc->mAddress = String8(address.c_str());
+        deviceDesc->setAddress(String8(address.c_str()));
     }
 
     AudioProfileTraits::Collection profiles;
@@ -535,7 +535,7 @@
         return Status::fromStatusT(status);
     }
     ALOGV("%s: adding device tag %s type %08x address %s", __func__,
-          deviceDesc->getName().string(), type, deviceDesc->mAddress.string());
+          deviceDesc->getName().string(), type, deviceDesc->address().string());
     return deviceDesc;
 }
 
@@ -742,7 +742,7 @@
             }
             ALOGV("%s: %s=%s",
                     __func__, tag, reinterpret_cast<const char*>(pointDefinition.get()));
-            Vector<int32_t> point;
+            std::vector<int32_t> point;
             collectionFromString<DefaultTraits<int32_t>>(
                     reinterpret_cast<const char*>(pointDefinition.get()), point, ",");
             if (point.size() != 2) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f07b797..64a2b8a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -149,13 +149,13 @@
 
             // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the outputs...)
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
+            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->address()) != NO_ERROR) {
                 mAvailableOutputDevices.remove(devDesc);
 
                 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                               devDesc->mAddress);
+                                               devDesc->address());
                 return INVALID_OPERATION;
             }
             // Propagate device availability to Engine
@@ -178,12 +178,12 @@
             ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
 
             // Send Disconnect to HALs
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
             // remove device from available output devices
             mAvailableOutputDevices.remove(devDesc);
 
-            checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
+            checkOutputsForDevice(devDesc, state, outputs, devDesc->address());
 
             // Propagate device availability to Engine
             mEngine->setDeviceConnectionState(devDesc, state);
@@ -265,11 +265,11 @@
 
             // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
             // parameters on newly connected devices (instead of opening the inputs...)
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            if (checkInputsForDevice(devDesc, state, inputs, devDesc->mAddress) != NO_ERROR) {
+            if (checkInputsForDevice(devDesc, state, inputs, devDesc->address()) != NO_ERROR) {
                 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                               devDesc->mAddress);
+                                               devDesc->address());
                 return INVALID_OPERATION;
             }
 
@@ -294,9 +294,9 @@
             ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
 
             // Set Disconnect to HALs
-            broadcastDeviceConnectionState(device, state, devDesc->mAddress);
+            broadcastDeviceConnectionState(device, state, devDesc->address());
 
-            checkInputsForDevice(devDesc, state, inputs, devDesc->mAddress);
+            checkInputsForDevice(devDesc, state, inputs, devDesc->address());
             mAvailableInputDevices.remove(devDesc);
 
             // Propagate device availability to Engine
@@ -780,17 +780,39 @@
     return output;
 }
 
-status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
-                                              audio_io_handle_t *output,
-                                              audio_session_t session,
-                                              audio_stream_type_t *stream,
-                                              uid_t uid,
-                                              const audio_config_t *config,
-                                              audio_output_flags_t *flags,
-                                              audio_port_handle_t *selectedDeviceId,
-                                              audio_port_handle_t *portId)
+status_t AudioPolicyManager::getAudioAttributes(audio_attributes_t *dstAttr,
+                                                const audio_attributes_t *srcAttr,
+                                                audio_stream_type_t srcStream)
 {
-    audio_attributes_t attributes;
+    if (srcAttr != NULL) {
+        if (!isValidAttributes(srcAttr)) {
+            ALOGE("%s invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+                    __func__,
+                    srcAttr->usage, srcAttr->content_type, srcAttr->flags,
+                    srcAttr->tags);
+            return BAD_VALUE;
+        }
+        *dstAttr = *srcAttr;
+    } else {
+        if (srcStream < AUDIO_STREAM_MIN || srcStream >= AUDIO_STREAM_PUBLIC_CNT) {
+            ALOGE("%s:  invalid stream type", __func__);
+            return BAD_VALUE;
+        }
+        stream_type_to_audio_attributes(srcStream, dstAttr);
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr,
+                                                 audio_io_handle_t *output,
+                                                 audio_session_t session,
+                                                 const audio_attributes_t *attr,
+                                                 audio_stream_type_t *stream,
+                                                 uid_t uid,
+                                                 const audio_config_t *config,
+                                                 audio_output_flags_t *flags,
+                                                 audio_port_handle_t *selectedDeviceId)
+{
     DeviceVector outputDevices;
     routing_strategy strategy;
     audio_devices_t device;
@@ -798,35 +820,20 @@
     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) {
-        return INVALID_OPERATION;
+    status_t status = getAudioAttributes(resultAttr, attr, *stream);
+    if (status != NO_ERROR) {
+        return status;
     }
 
-    if (attr != NULL) {
-        if (!isValidAttributes(attr)) {
-            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
-                  attr->usage, attr->content_type, attr->flags,
-                  attr->tags);
-            return BAD_VALUE;
-        }
-        attributes = *attr;
-    } else {
-        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
-            ALOGE("getOutputForAttr():  invalid stream type");
-            return BAD_VALUE;
-        }
-        stream_type_to_audio_attributes(*stream, &attributes);
-    }
-
-    ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x"
+    ALOGV("%s usage=%d, content=%d, tag=%s flags=%08x"
           " session %d selectedDeviceId %d",
-          attributes.usage, attributes.content_type, attributes.tags, attributes.flags,
+          __func__,
+          resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags,
           session, requestedDeviceId);
 
-    *stream = streamTypefromAttributesInt(&attributes);
+    *stream = streamTypefromAttributesInt(resultAttr);
 
-    strategy = getStrategyForAttr(&attributes);
+    strategy = getStrategyForAttr(resultAttr);
 
     // First check for explicit routing (eg. setPreferredDevice)
     if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -836,30 +843,30 @@
     } else {
         // If no explict route, is there a matching dynamic policy that applies?
         sp<SwAudioOutputDescriptor> desc;
-        if (mPolicyMixes.getOutputForAttr(attributes, uid, desc) == NO_ERROR) {
+        if (mPolicyMixes.getOutputForAttr(*resultAttr, uid, desc) == NO_ERROR) {
             ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
             if (!audio_has_proportional_frames(config->format)) {
                 return BAD_VALUE;
             }
-            *stream = streamTypefromAttributesInt(&attributes);
+            *stream = streamTypefromAttributesInt(resultAttr);
             *output = desc->mIoHandle;
             AudioMix *mix = desc->mPolicyMix;
             sp<DeviceDescriptor> deviceDesc =
                 mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress);
             *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
-            ALOGV("getOutputForAttr() returns output %d", *output);
-            goto exit;
+            ALOGV("%s returns output %d", __func__, *output);
+            return NO_ERROR;
         }
 
         // Virtual sources must always be dynamicaly or explicitly routed
-        if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
-            ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
+        if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+            ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__);
             return BAD_VALUE;
         }
         device = getDeviceForStrategy(strategy, false /*fromCache*/);
     }
 
-    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+    if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
         *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
     }
 
@@ -869,7 +876,7 @@
     // to getOutputForDevice.
     // TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
     if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
-        (*stream == AUDIO_STREAM_MUSIC || attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
+        (*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
         audio_is_linear_pcm(config->format) &&
         isInCall()) {
         if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
@@ -880,9 +887,9 @@
         }
     }
 
-    ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
+    ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
           "flags %#x",
-          device, config->sample_rate, config->format, config->channel_mask, *flags);
+          __func__, device, config->sample_rate, config->format, config->channel_mask, *flags);
 
     *output = AUDIO_IO_HANDLE_NONE;
     if (msdDevice != AUDIO_DEVICE_NONE) {
@@ -903,25 +910,50 @@
     }
 
     outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
-    *selectedDeviceId = outputDevices.size() > 0 ? outputDevices.itemAt(0)->getId()
-            : AUDIO_PORT_HANDLE_NONE;
+    *selectedDeviceId = getFirstDeviceId(outputDevices);
 
-exit:
+    ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uid_t uid,
+                                              const audio_config_t *config,
+                                              audio_output_flags_t *flags,
+                                              audio_port_handle_t *selectedDeviceId,
+                                              audio_port_handle_t *portId)
+{
+    // The supplied portId must be AUDIO_PORT_HANDLE_NONE
+    if (*portId != AUDIO_PORT_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
+    audio_attributes_t resultAttr;
+    status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
+            config, flags, selectedDeviceId);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
     audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
         .format = config->format,
         .channel_mask = config->channel_mask };
     *portId = AudioPort::getNextUniqueId();
 
     sp<TrackClientDescriptor> clientDesc =
-        new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig,
+        new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
                                   requestedDeviceId, *stream,
-                                  getStrategyForAttr(&attributes),
+                                  getStrategyForAttr(&resultAttr),
                                   *flags);
     sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
     outputDesc->addClient(clientDesc);
 
-    ALOGV("  getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d",
-          *output, *selectedDeviceId, *portId);
+    ALOGV("%s returns output %d selectedDeviceId %d for port ID %d",
+          __func__, *output, requestedDeviceId, *portId);
 
     return NO_ERROR;
 }
@@ -1020,8 +1052,7 @@
                 new SwAudioOutputDescriptor(profile, mpClientInterface);
 
         DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
-        String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
-                : String8("");
+        String8 address = getFirstDeviceAddress(outputDevices);
 
         // MSD patch may be using the only output stream that can service this request. Release
         // MSD patch to prioritize this request over any active output on MSD.
@@ -1722,10 +1753,7 @@
     }
 
     // Explicit routing?
-    sp<DeviceDescriptor> deviceDesc;
-    if (*selectedDeviceId != AUDIO_PORT_HANDLE_NONE) {
-        deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
-    }
+    sp<DeviceDescriptor> deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
 
     // special case for mmap capture: if an input IO handle is specified, we reuse this input if
     // possible
@@ -1831,8 +1859,7 @@
 exit:
 
     inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
-    *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
-                                                : AUDIO_PORT_HANDLE_NONE;
+    *selectedDeviceId = getFirstDeviceId(inputDevices);
 
     isSoundTrigger = inputSource == AUDIO_SOURCE_HOTWORD &&
         mSoundTriggerSessions.indexOfKey(session) > 0;
@@ -1963,7 +1990,7 @@
     if (address == "") {
         DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
         // the inputs vector must be of size >= 1, but we don't want to crash here
-        address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8("");
+        address = getFirstDeviceAddress(inputDevices);
     }
 
     status_t status = inputDesc->open(&lConfig, device, address,
@@ -2930,7 +2957,7 @@
             }
 
             if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                           devDesc->mAddress,
+                                                           devDesc->address(),
                                                            patch->sources[0].sample_rate,
                                                            NULL,  // updatedSamplingRate
                                                            patch->sources[0].format,
@@ -2987,7 +3014,7 @@
             }
 
             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
-                                                          devDesc->mAddress,
+                                                          devDesc->address(),
                                                           patch->sinks[0].sample_rate,
                                                           NULL, /*updatedSampleRate*/
                                                           patch->sinks[0].format,
@@ -3050,8 +3077,10 @@
                 // create a software bridge in PatchPanel if:
                 // - source and sink devices are on different HW modules OR
                 // - audio HAL version is < 3.0
+                // - audio HAL version is >= 3.0 but no route has been declared between devices
                 if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
-                        (srcDeviceDesc->mModule->getHalVersionMajor() < 3)) {
+                        (srcDeviceDesc->getModuleVersionMajor() < 3) ||
+                        !srcDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc)) {
                     // support only one sink device for now to simplify output selection logic
                     if (patch->num_sinks > 1) {
                         return INVALID_OPERATION;
@@ -3395,16 +3424,25 @@
 
     audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
 
-    if (srcDeviceDesc->getAudioPort()->mModule->getHandle() ==
-            sinkDeviceDesc->getAudioPort()->mModule->getHandle() &&
-            srcDeviceDesc->getAudioPort()->mModule->getHalVersionMajor() >= 3 &&
+    if (srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) &&
+            srcDeviceDesc->getModuleVersionMajor() >= 3 &&
+            sinkDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc) &&
             srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
-        ALOGV("%s AUDIO_DEVICE_API_VERSION_3_0", __FUNCTION__);
+        ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
+        // TODO: may explicitly specify whether we should use HW or SW patch
         //   create patch between src device and output device
         //   create Hwoutput and add to mHwOutputs
     } else {
-        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs);
-        audio_io_handle_t output = selectOutput(outputs);
+        audio_attributes_t resultAttr;
+        audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+        config.sample_rate = sourceDesc->config().sample_rate;
+        config.channel_mask = sourceDesc->config().channel_mask;
+        config.format = sourceDesc->config().format;
+        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+        audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+        getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
+                &attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId);
         if (output == AUDIO_IO_HANDLE_NONE) {
             ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice);
             return INVALID_OPERATION;
@@ -3437,6 +3475,13 @@
                   __FUNCTION__, status);
             return INVALID_OPERATION;
         }
+
+        if (outputDesc->getClient(sourceDesc->portId()) != nullptr) {
+            ALOGW("%s source portId has already been attached to outputDesc", __func__);
+            return INVALID_OPERATION;
+        }
+        outputDesc->addClient(sourceDesc);
+
         uint32_t delayMs = 0;
         status = startSource(outputDesc, sourceDesc, &delayMs);
 
@@ -3615,7 +3660,7 @@
             AUDIO_DEVICE_OUT_HDMI);
     for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiOutputDevices[i]->mAddress;
+        String8 address = hdmiOutputDevices[i]->address();
         String8 name = hdmiOutputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -3635,7 +3680,7 @@
                 AUDIO_DEVICE_IN_HDMI);
     for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
         // Simulate reconnection to update enabled surround sound formats.
-        String8 address = hdmiInputDevices[i]->mAddress;
+        String8 address = hdmiInputDevices[i]->address();
         String8 name = hdmiInputDevices[i]->getName();
         status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
                                                       AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
@@ -3893,8 +3938,7 @@
             const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
             const DeviceVector &devicesForType = supportedDevices.getDevicesFromTypeMask(
                     profileType);
-            String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
-                    : String8("");
+            String8 address = getFirstDeviceAddress(devicesForType);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
             status_t status = outputDesc->open(nullptr, profileType, address,
                                            AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
@@ -3948,8 +3992,7 @@
 
             DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(profileType);
             //   the inputs vector must be of size >= 1, but we don't want to crash here
-            String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress
-                    : String8("");
+            String8 address = getFirstDeviceAddress(inputDevices);
             ALOGV("  for input device 0x%x using address %s", profileType, address.string());
             ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!");
 
@@ -4011,11 +4054,11 @@
     }
     // If microphones address is empty, set it according to device type
     for (size_t i = 0; i  < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->mAddress.isEmpty()) {
+        if (mAvailableInputDevices[i]->address().isEmpty()) {
             if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mAvailableInputDevices[i]->mAddress = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->address() = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
             } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mAvailableInputDevices[i]->mAddress = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
+                mAvailableInputDevices[i]->address() = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
             }
         }
     }
@@ -5184,8 +5227,9 @@
         if (!deviceList.isEmpty()) {
             PatchBuilder patchBuilder;
             patchBuilder.addSource(outputDesc);
-            for (size_t i = 0; i < deviceList.size() && i < AUDIO_PATCH_PORTS_MAX; i++) {
-                patchBuilder.addSink(deviceList.itemAt(i));
+            ALOG_ASSERT(deviceList.size() <= AUDIO_PATCH_PORTS_MAX, "Too many sink ports");
+            for (const auto &device : deviceList) {
+                patchBuilder.addSink(device);
             }
             installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index d0708b8..86993d4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -519,6 +519,19 @@
             return mAvailableInputDevices.getDeviceTypesFromHwModule(
                     mPrimaryOutput->getModuleHandle());
         }
+        /**
+         * @brief getFirstDeviceId of the Device Vector
+         * @return if the collection is not empty, it returns the first device Id,
+         *         otherwise AUDIO_PORT_HANDLE_NONE
+         */
+        audio_port_handle_t getFirstDeviceId(const DeviceVector &devices) const
+        {
+            return (devices.size() > 0) ? devices.itemAt(0)->getId() : AUDIO_PORT_HANDLE_NONE;
+        }
+        String8 getFirstDeviceAddress(const DeviceVector &devices) const
+        {
+            return (devices.size() > 0) ? devices.itemAt(0)->address() : String8("");
+        }
 
         uint32_t updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs = 0);
         sp<AudioPatch> createTelephonyPatch(bool isRx, audio_devices_t device, uint32_t delayMs);
@@ -661,6 +674,21 @@
                 const String8& address /*in*/,
                 SortedVector<audio_io_handle_t>& outputs /*out*/);
         uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
+        // internal method, get audio_attributes_t from either a source audio_attributes_t
+        // or audio_stream_type_t, respectively.
+        status_t getAudioAttributes(audio_attributes_t *dstAttr,
+                const audio_attributes_t *srcAttr,
+                audio_stream_type_t srcStream);
+        // internal method, called by getOutputForAttr() and connectAudioSource.
+        status_t getOutputForAttrInt(audio_attributes_t *resultAttr,
+                audio_io_handle_t *output,
+                audio_session_t session,
+                const audio_attributes_t *attr,
+                audio_stream_type_t *stream,
+                uid_t uid,
+                const audio_config_t *config,
+                audio_output_flags_t *flags,
+                audio_port_handle_t *selectedDeviceId);
         // internal method to return the output handle for the given device and format
         audio_io_handle_t getOutputForDevice(
                 audio_devices_t device,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index ee5d6ff..f233971 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -38,6 +38,7 @@
 #include <media/AudioEffect.h>
 #include <media/AudioParameter.h>
 #include <mediautils/ServiceUtilities.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
 
 #include <system/audio.h>
 #include <system/audio_policy.h>
@@ -84,6 +85,9 @@
 
     mUidPolicy = new UidPolicy(this);
     mUidPolicy->registerSelf();
+
+    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+    mSensorPrivacyPolicy->registerSelf();
 }
 
 AudioPolicyService::~AudioPolicyService()
@@ -99,6 +103,9 @@
 
     mUidPolicy->unregisterSelf();
     mUidPolicy.clear();
+
+    mSensorPrivacyPolicy->unregisterSelf();
+    mSensorPrivacyPolicy.clear();
 }
 
 // A notification client is always registered by AudioSystem when the client process
@@ -375,6 +382,12 @@
     bool isAssistantOnTop = false;
     bool isSensitiveActive = false;
 
+    // if Sensor Privacy is enabled then all recordings should be silenced.
+    if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+        silenceAllRecordings_l();
+        return;
+    }
+
     for (size_t i =0; i < mAudioRecordClients.size(); i++) {
         sp<AudioRecordClient> current = mAudioRecordClients[i];
         if (!current->active) continue;
@@ -445,6 +458,13 @@
     }
 }
 
+void AudioPolicyService::silenceAllRecordings_l() {
+    for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
+        sp<AudioRecordClient> current = mAudioRecordClients[i];
+        setAppState_l(current->uid, APP_STATE_IDLE);
+    }
+}
+
 /* static */
 app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
     switch (amState) {
@@ -858,6 +878,31 @@
     return it != mA11yUids.end();
 }
 
+// -----------  AudioPolicyService::SensorPrivacyService implementation ----------
+void AudioPolicyService::SensorPrivacyPolicy::registerSelf() {
+    SensorPrivacyManager spm;
+    mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
+    spm.addSensorPrivacyListener(this);
+}
+
+void AudioPolicyService::SensorPrivacyPolicy::unregisterSelf() {
+    SensorPrivacyManager spm;
+    spm.removeSensorPrivacyListener(this);
+}
+
+bool AudioPolicyService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+    return mSensorPrivacyEnabled;
+}
+
+binder::Status AudioPolicyService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
+    mSensorPrivacyEnabled = enabled;
+    sp<AudioPolicyService> service = mService.promote();
+    if (service != nullptr) {
+        service->updateUidStates();
+    }
+    return binder::Status::ok();
+}
+
 // -----------  AudioPolicyService::AudioCommandThread implementation ----------
 
 AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 23c3daa..45d37dc 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -33,6 +33,7 @@
 #include <media/AudioPolicy.h>
 #include "AudioPolicyEffects.h"
 #include "managerdefault/AudioPolicyManager.h"
+#include <android/hardware/BnSensorPrivacyListener.h>
 
 #include <unordered_map>
 
@@ -279,6 +280,8 @@
     void updateUidStates();
     void updateUidStates_l();
 
+    void silenceAllRecordings_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
@@ -334,6 +337,27 @@
         std::vector<uid_t> mA11yUids;
     };
 
+    // If sensor privacy is enabled then all apps, including those that are active, should be
+    // prevented from recording. This is handled similar to idle UIDs, any app that attempts
+    // to record while sensor privacy is enabled will receive buffers with zeros. As soon as
+    // sensor privacy is disabled active apps will receive the expected data when recording.
+    class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener {
+        public:
+            explicit SensorPrivacyPolicy(wp<AudioPolicyService> service)
+                    : mService(service) {}
+
+            void registerSelf();
+            void unregisterSelf();
+
+            bool isSensorPrivacyEnabled();
+
+            binder::Status onSensorPrivacyChanged(bool enabled);
+
+        private:
+            wp<AudioPolicyService> mService;
+            std::atomic_bool mSensorPrivacyEnabled;
+    };
+
     // Thread used to send audio config commands to audio flinger
     // For audio config commands, it is necessary because audio flinger requires that the calling
     // process (user) has permission to modify audio settings.
@@ -718,6 +742,8 @@
     audio_mode_t mPhoneState;
 
     sp<UidPolicy> mUidPolicy;
+    sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
     DefaultKeyedVector< audio_port_handle_t, sp<AudioRecordClient> >   mAudioRecordClients;
     DefaultKeyedVector< audio_port_handle_t, sp<AudioPlaybackClient> >   mAudioPlaybackClients;
 };
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c1a4c11..46fbc3e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -256,7 +256,7 @@
         Vector<int32_t> outputStreamIds;
         std::vector<std::string> requestedPhysicalIds;
         if (request.mSurfaceList.size() > 0) {
-            for (sp<Surface> surface : request.mSurfaceList) {
+            for (const sp<Surface>& surface : request.mSurfaceList) {
                 if (surface == 0) continue;
 
                 int32_t streamId;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 856af13..12fbf82 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -175,7 +175,7 @@
         session->interfaceChain([](
             ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                 ALOGV("Session interface chain:");
-                for (auto iface : interfaceChain) {
+                for (const auto& iface : interfaceChain) {
                     ALOGV("  %s", iface.c_str());
                 }
             });
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 789548d..3b6dc80 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -108,6 +108,7 @@
 LOCAL_MODULE := mediaswcodec
 LOCAL_INIT_RC := mediaswcodec.rc
 LOCAL_32_BIT_ONLY := true
+LOCAL_SANITIZE := scudo
 
 sanitizer_runtime_libraries :=
 llndk_libraries :=
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index 386abb2..79fea25 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -37,6 +37,12 @@
 static const char kVendorSeccompPolicyPath[] =
         "/vendor/etc/seccomp_policy/mediacodec.policy";
 
+// Disable Scudo's mismatch allocation check, as it is being triggered
+// by some third party code.
+extern "C" const char *__scudo_default_options() {
+  return "DeallocationTypeMismatch=false";
+}
+
 int main(int argc __unused, char** /*argv*/)
 {
     LOG(INFO) << "media swcodec service starting";
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 7c9c727..e31eadc 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -38,13 +38,6 @@
 LOCAL_REQUIRED_MODULES_x86 := crash_dump.policy mediaextractor.policy
 LOCAL_REQUIRED_MODULES_x86_64 := crash_dump.policy mediaextractor.policy
 
-# extractor libraries
-LOCAL_REQUIRED_MODULES += \
-    libmkvextractor \
-    libmp4extractor \
-    libmpeg2extractor \
-    liboggextractor \
-
 LOCAL_SRC_FILES := main_extractorservice.cpp
 LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
     liblog libbase libicuuc libavservices_minijail
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index cca1895..a1fc0ea 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -108,7 +108,7 @@
         const AAudioStreamConfiguration &configuration) {
     sp<AAudioServiceEndpoint> endpoint;
     mExclusiveSearchCount++;
-    for (const auto ep : mExclusiveStreams) {
+    for (const auto& ep : mExclusiveStreams) {
         if (ep->matches(configuration)) {
             mExclusiveFoundCount++;
             endpoint = ep;
@@ -126,7 +126,7 @@
         const AAudioStreamConfiguration &configuration) {
     sp<AAudioServiceEndpointShared> endpoint;
     mSharedSearchCount++;
-    for (const auto ep  : mSharedStreams) {
+    for (const auto& ep  : mSharedStreams) {
         if (ep->matches(configuration)) {
             mSharedFoundCount++;
             endpoint = ep;
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 539735a..4dfb62a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -65,7 +65,7 @@
     result << "    Connected:            " << mConnected.load() << "\n";
     result << "    Registered Streams:" << "\n";
     result << AAudioServiceStreamShared::dumpHeader() << "\n";
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         result << stream->dump() << "\n";
     }
 
@@ -78,7 +78,7 @@
 // @return true if stream found
 bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
     std::lock_guard<std::mutex> lock(mLockStreams);
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         if (stream->getPortHandle() == portHandle) {
             return true;
         }
@@ -89,7 +89,7 @@
 void AAudioServiceEndpoint::disconnectRegisteredStreams() {
     std::lock_guard<std::mutex> lock(mLockStreams);
     mConnected.store(false);
-    for (const auto stream : mRegisteredStreams) {
+    for (const auto& stream : mRegisteredStreams) {
         ALOGD("disconnectRegisteredStreams() stop and disconnect %p", stream.get());
         stream->stop();
         stream->disconnect();
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 7ae7f1b..37d105b 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -81,9 +81,10 @@
         { // brackets are for lock_guard
 
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (const auto clientStream : mRegisteredStreams) {
-                if (clientStream->isRunning()) {
+            for (const auto& clientStream : mRegisteredStreams) {
+                if (clientStream->isRunning() && !clientStream->isSuspended()) {
                     int64_t clientFramesWritten = 0;
+
                     sp<AAudioServiceStreamShared> streamShared =
                             static_cast<AAudioServiceStreamShared *>(clientStream.get());
 
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index e4dbee1..6c28083 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -371,7 +371,7 @@
     float volume = values[0];
     ALOGD("%s(%p) volume[0] = %f", __func__, this, volume);
     std::lock_guard<std::mutex> lock(mLockStreams);
-    for(const auto stream : mRegisteredStreams) {
+    for(const auto& stream : mRegisteredStreams) {
         stream->onVolumeChanged(volume);
     }
 };
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 923a1a4..1e1c552 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -80,10 +80,14 @@
             int64_t mmapFramesWritten = getStreamInternal()->getFramesWritten();
 
             std::lock_guard <std::mutex> lock(mLockStreams);
-            for (const auto clientStream : mRegisteredStreams) {
+            for (const auto& clientStream : mRegisteredStreams) {
                 int64_t clientFramesRead = 0;
                 bool allowUnderflow = true;
 
+                if (clientStream->isSuspended()) {
+                    continue; // dead stream
+                }
+
                 aaudio_stream_state_t state = clientStream->getState();
                 if (state == AAUDIO_STREAM_STATE_STOPPING) {
                     allowUnderflow = false; // just read what is already in the FIFO
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 354b36a..defbb7b 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -179,6 +179,7 @@
     }
 
     setFlowing(false);
+    setSuspended(false);
 
     // Start with fresh presentation timestamps.
     mAtomicTimestamp.clear();
@@ -345,7 +346,9 @@
     }
     int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
     if (count != 1) {
-        ALOGE("%s(): Queue full. Did client die? %s", __func__, getTypeText());
+        ALOGW("%s(): Queue full. Did client stop? Suspending stream. what = %u, %s",
+              __func__, command->what, getTypeText());
+        setSuspended(true);
         return AAUDIO_ERROR_WOULD_BLOCK;
     } else {
         return AAUDIO_OK;
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index a1815d0..7904b25 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -204,6 +204,20 @@
     }
 
     /**
+     * Set false when the stream should not longer be processed.
+     * This may be caused by a message queue overflow.
+     * Set true when stream is started.
+     * @param suspended
+     */
+    void setSuspended(bool suspended) {
+        mSuspended = suspended;
+    }
+
+    bool isSuspended() const {
+        return mSuspended;
+    }
+
+    /**
      * Atomically increment the number of active references to the stream by AAudioService.
      *
      * This is called under a global lock in AAudioStreamTracker.
@@ -304,7 +318,12 @@
     // This is modified under a global lock in AAudioStreamTracker.
     int32_t                 mCallingCount = 0;
 
+    // This indicates that a stream that is being referenced by a binder call needs to closed.
     std::atomic<bool>       mCloseNeeded{false};
+
+    // This indicate that a running stream should not be processed because of an error,
+    // for example a full message queue. Note that this atomic is unrelated to mCloseNeeded.
+    std::atomic<bool>       mSuspended{false};
 };
 
 } /* namespace aaudio */