Merge "media.c2 aidl: Apply bufferpool based allocator interface change" into main
diff --git a/media/aconfig/Android.bp b/media/aconfig/Android.bp
index 96bf4f5..f95d723 100644
--- a/media/aconfig/Android.bp
+++ b/media/aconfig/Android.bp
@@ -14,6 +14,7 @@
     name: "aconfig_mediacodec_flags_c_lib",
     min_sdk_version: "30",
     vendor_available: true,
+    double_loadable: true,
     apex_available: [
         "//apex_available:platform",
         "com.android.media.swcodec",
diff --git a/media/codec2/components/aom/C2SoftAomEnc.cpp b/media/codec2/components/aom/C2SoftAomEnc.cpp
index 71909e5..7c9d3e8 100644
--- a/media/codec2/components/aom/C2SoftAomEnc.cpp
+++ b/media/codec2/components/aom/C2SoftAomEnc.cpp
@@ -338,6 +338,19 @@
 }
 
 c2_status_t C2SoftAomEnc::onStop() {
+    IntfImpl::Lock lock = mIntf->lock();
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync = mIntf->getRequestSync_l();
+    lock.unlock();
+    if (requestSync != mRequestSync) {
+        // we can handle IDR immediately
+        if (requestSync->value) {
+            // unset request
+            C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE);
+            std::vector<std::unique_ptr<C2SettingResult>> failures;
+            mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures);
+        }
+        mRequestSync = requestSync;
+    }
     onRelease();
     return C2_OK;
 }
diff --git a/media/codec2/hal/aidl/BufferTypes.cpp b/media/codec2/hal/aidl/BufferTypes.cpp
index bc4948b..a0e6aa5 100644
--- a/media/codec2/hal/aidl/BufferTypes.cpp
+++ b/media/codec2/hal/aidl/BufferTypes.cpp
@@ -302,7 +302,7 @@
                             "invalid receiver connection id (0).";
             return bufferpool2::ResultStatus::CRITICAL_ERROR;
         } else {
-            if (isNewConnection) {
+            if (foundConnection == mConnections.end()) {
                 foundConnection = mConnections.try_emplace(
                         connectionId, receiverConnectionId, now).first;
             } else {
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
index 1c5c7d6..2054fe6 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/Android.bp
@@ -44,6 +44,7 @@
         "res/bbb_opus_stereo_128kbps_48000hz.info",
         "res/bbb_opus_stereo_128kbps_48000hz.opus",
         "res/bbb_raw_1ch_8khz_s32le.info",
+        "res/bbb_raw_1ch_8khz_s32le_largeframe.info",
         "res/bbb_raw_1ch_8khz_s32le.raw",
         "res/bbb_vorbis_stereo_128kbps_48000hz.info",
         "res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index c7c04c5..0c30d95 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -32,7 +32,11 @@
 #include <codec2/hidl/client.h>
 
 #include "media_c2_hidl_test_common.h"
-using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
+
+using DecodeTestParameters = std::tuple<std::string /*instance_name*/,
+        std::string /*component_name*/,
+        uint32_t /*stream_index*/,
+        bool /*signal end-of-stream nor not*/>;
 static std::vector<DecodeTestParameters> gDecodeTestParameters;
 
 using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
@@ -56,6 +60,7 @@
         {"g711-mlaw", "bbb_g711mulaw_1ch_8khz.raw", "bbb_g711mulaw_1ch_8khz.info"},
         {"gsm", "bbb_gsm_1ch_8khz_13kbps.raw", "bbb_gsm_1ch_8khz_13kbps.info"},
         {"raw", "bbb_raw_1ch_8khz_s32le.raw", "bbb_raw_1ch_8khz_s32le.info"},
+        {"raw", "bbb_raw_1ch_8khz_s32le.raw", "bbb_raw_1ch_8khz_s32le_largeframe.info"},
         {"flac", "bbb_flac_stereo_680kbps_48000hz.flac", "bbb_flac_stereo_680kbps_48000hz.info"},
 };
 
@@ -137,6 +142,9 @@
     struct outputMetaData {
         uint64_t timestampUs;
         uint32_t rangeLength;
+        // The following is used only if C2AccessUnitInfos::output
+        // is present as part of C2Buffer.
+        std::vector<C2AccessUnitInfosStruct> largeFrameInfo;
     };
     // callback function to process onWorkDone received by Listener
     void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
@@ -161,8 +169,18 @@
                                                    .capacity();
                     // List of timestamp values and output size to calculate timestamp
                     if (mTimestampDevTest) {
-                        outputMetaData meta = {mTimestampUs, rangeLength};
+                        outputMetaData meta = {mTimestampUs, rangeLength, {}};
                         oBufferMetaData.push_back(meta);
+                        std::shared_ptr<const C2AccessUnitInfos::output> inBufferInfo =
+                                std::static_pointer_cast<const C2AccessUnitInfos::output>(
+                                work->worklets.front()->output.buffers[0]->getInfo(
+                                C2AccessUnitInfos::output::PARAM_TYPE));
+                        if (inBufferInfo) {
+                            for (int nMeta = 0; nMeta < inBufferInfo->flexCount(); nMeta++) {
+                                oBufferMetaData.back().largeFrameInfo.push_back(
+                                        inBufferInfo->m.values[nMeta]);
+                            }
+                        }
                     }
                 }
                 bool mCsd = false;
@@ -203,6 +221,12 @@
     std::string mInfoFile;
     size_t mStreamIndex = 0;
 
+    // These are used only with large frame codec
+    // Specifies the maximum output size in bytes.
+    uint32_t mMaxOutputSize;
+    //Specifies the threshold output size in bytes.
+    uint32_t mOutputThresholdSize;
+
   protected:
     static void description(const std::string& description) {
         RecordProperty("description", description);
@@ -249,6 +273,96 @@
     ALOGV("Component Valid");
 }
 
+bool isLargeAudioFrameSupported(const std::shared_ptr<android::Codec2Client::Component> &comp,
+        std::vector<C2FieldSupportedValues>& supportedValues) {
+    C2LargeFrame::output largeFrameParams;
+    std::vector<C2FieldSupportedValuesQuery> validValueInfos = {
+            C2FieldSupportedValuesQuery::Current(
+                    C2ParamField(&largeFrameParams, &C2LargeFrame::maxSize)),
+            C2FieldSupportedValuesQuery::Current(
+                    C2ParamField(&largeFrameParams,
+                            &C2LargeFrame::thresholdSize))};
+    c2_status_t c2err = comp->querySupportedValues(validValueInfos, C2_DONT_BLOCK);
+    if (c2err != C2_OK || validValueInfos.size() != 2) {
+        return false;
+    }
+    supportedValues.clear();
+    for (int i = 0; i < 2; i++) {
+        if (validValueInfos[i].values.type == C2FieldSupportedValues::EMPTY) {
+            return false;
+        }
+        supportedValues.push_back(validValueInfos[i].values);
+    }
+    return true;
+}
+
+c2_status_t configureLargeFrameParams(const std::shared_ptr<android::Codec2Client::Component> &comp,
+        uint32_t& maxOutput, uint32_t& outputThreshold,
+        const std::vector<C2FieldSupportedValues>& supportedValues) {
+
+    if (supportedValues.empty()) {
+        ALOGE("Error: No supported values in large audio frame params");
+        return C2_BAD_VALUE;
+    }
+
+    auto boundBySupportedValues = [](const C2FieldSupportedValues& supportedValues, uint32_t& value)
+            -> c2_status_t {
+        uint32_t oBufMin = 0, oBufMax = 0;
+        switch (supportedValues.type) {
+            case C2FieldSupportedValues::type_t::RANGE:
+            {
+                const auto& range = supportedValues.range;
+                oBufMax = (uint32_t)(range.max).ref<uint32_t>();
+                oBufMin = (uint32_t)(range.min).ref<uint32_t>();
+                value = (value > oBufMax) ? oBufMax :
+                        (value < oBufMin) ? oBufMin : value;
+                break;
+            }
+
+            case C2FieldSupportedValues::type_t::VALUES:
+            {
+                uint32_t lastValue;
+                for (const C2Value::Primitive& prim : supportedValues.values) {
+                    lastValue = (uint32_t)prim.ref<uint32_t>();
+                    if (lastValue > value) {
+                        value = lastValue;
+                        break;
+                    }
+                }
+                if (value > lastValue) {
+                    value = lastValue;
+                }
+                break;
+            }
+
+            default:
+                return C2_BAD_VALUE;
+            }
+        return C2_OK;
+    };
+    c2_status_t c2_err = boundBySupportedValues(supportedValues[0], maxOutput);
+    if (c2_err != C2_OK) {
+        return c2_err;
+    }
+    c2_err = boundBySupportedValues(supportedValues[1], outputThreshold);
+    if (c2_err != C2_OK) {
+        return c2_err;
+    }
+    if (outputThreshold > maxOutput) {
+        outputThreshold = maxOutput;
+    }
+    ALOGV("Setting large frame format : Max: %d - Threshold: %d", maxOutput, outputThreshold);
+    std::vector<std::unique_ptr<C2SettingResult>> failures;
+    C2LargeFrame::output largeFrameParams(0u, maxOutput, outputThreshold);
+    std::vector<C2Param*> configParam{&largeFrameParams};
+    c2_status_t status = comp->config(configParam, C2_DONT_BLOCK, &failures);
+    if (status != C2_OK || failures.size() != 0u) {
+        ALOGE("Large frame Audio configuration failed for maxSize: %d, thresholdSize: %d",
+                maxOutput, outputThreshold);
+    }
+    return status;
+}
+
 // Set Default config param.
 bool setupConfigParam(const std::shared_ptr<android::Codec2Client::Component>& component,
                       int32_t* bitStreamInfo) {
@@ -317,6 +431,10 @@
     typedef std::unique_lock<std::mutex> ULock;
     int frameID = offset;
     int maxRetry = 0;
+    std::shared_ptr<C2Buffer> buffer;
+    std::vector<C2FieldSupportedValues> largeFrameValues;
+    bool isComponentSupportsLargeAudioFrame = isLargeAudioFrameSupported(component,
+            largeFrameValues);
     while (1) {
         if (frameID == (int)Info->size() || frameID == (offset + range)) break;
         uint32_t flags = 0;
@@ -376,7 +494,17 @@
 
             memcpy(view.base(), data, size);
 
-            work->input.buffers.emplace_back(new LinearBuffer(block));
+            buffer.reset(new LinearBuffer(block));
+            if (!(*Info)[frameID].largeFrameInfo.empty() && isComponentSupportsLargeAudioFrame) {
+                const std::vector<C2AccessUnitInfosStruct>& meta =
+                        (*Info)[frameID].largeFrameInfo;
+                ALOGV("Large Audio frame supported for %s, frameID: %d, size: %zu",
+                        component->getName().c_str(), frameID, meta.size());
+                const std::shared_ptr<C2AccessUnitInfos::input> largeFrame =
+                        C2AccessUnitInfos::input::AllocShared(meta.size(), 0u, meta);
+                buffer->setInfo(largeFrame);
+            }
+            work->input.buffers.push_back(buffer);
             free(data);
         }
         work->worklets.clear();
@@ -403,9 +531,37 @@
     auto itOut = oBufferMetaData.begin();
     EXPECT_EQ(*itIn, itOut->timestampUs);
     uint64_t expectedTimeStamp = *itIn;
-    while (itOut != oBufferMetaData.end()) {
+    bool err= false;
+    while (!err && itOut != oBufferMetaData.end()) {
         EXPECT_EQ(expectedTimeStamp, itOut->timestampUs);
         if (expectedTimeStamp != itOut->timestampUs) break;
+        if (!itOut->largeFrameInfo.empty()) {
+            // checking large audio frame metadata
+            if (itOut->largeFrameInfo[0].timestamp != itOut->timestampUs) {
+                ALOGE("Metadata first time stamp doesn't match");
+                err = true;
+                break;
+            }
+            uint64_t totalSize = 0;
+            uint64_t sampleSize = 0;
+            int64_t nextTimestamp = itOut->timestampUs;
+            for (auto& meta : itOut->largeFrameInfo) {
+                if (nextTimestamp != meta.timestamp) {
+                    ALOGE("Metadata timestamp error: expect: %lld, got: %lld",
+                            (long long)nextTimestamp, (long long)meta.timestamp);
+                    err = true;
+                    break;
+                }
+                totalSize += meta.size;
+                sampleSize = (meta.size / (nChannels * 2));
+                nextTimestamp += sampleSize * 1000000ll / nSampleRate;
+            }
+            if (totalSize != itOut->rangeLength) {
+                ALOGE("Metadata size error: expected:%lld, got: %d",
+                        (long long)totalSize, itOut->rangeLength);
+                err = true;
+            }
+        }
         // buffer samples = ((total bytes) / (ac * (bits per sample / 8))
         samplesReceived += ((itOut->rangeLength) / (nChannels * 2));
         expectedTimeStamp = samplesReceived * 1000000ll / nSampleRate;
@@ -453,7 +609,8 @@
     android::Vector<FrameInfo> Info;
 
     int32_t numCsds = populateInfoVector(mInfoFile, &Info, mTimestampDevTest, &mTimestampUslist);
-    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << mInfoFile;
+    ASSERT_GE(numCsds, 0) << "Error in parsing input info file: " << mInfoFile <<
+            " #CSD " << numCsds;
 
     // Reset total no of frames received
     mFramesReceived = 0;
@@ -474,10 +631,23 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    getInputChannelInfo(mComponent, mMime, bitStreamInfo);
+    std::vector<C2FieldSupportedValues> supportedValues;
+    if (!Info.top().largeFrameInfo.empty()) {
+        if (!isLargeAudioFrameSupported(mComponent, supportedValues)) {
+            GTEST_SKIP() << "As component does not support large frame";
+        }
+        // time_sec * sample_rate * channel_count * 2 (bytes_per_channel)
+        mMaxOutputSize = 60 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        mOutputThresholdSize = 50 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        ASSERT_EQ(configureLargeFrameParams(mComponent, mMaxOutputSize,
+                mOutputThresholdSize, supportedValues), C2_OK);
+    }
     ASSERT_EQ(mComponent->start(), C2_OK);
     std::ifstream eleStream;
     eleStream.open(mInputFile, 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(), signalEOS));
@@ -529,6 +699,18 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    getInputChannelInfo(mComponent, mMime, bitStreamInfo);
+    std::vector<C2FieldSupportedValues> supportedValues;
+    if (!Info.top().largeFrameInfo.empty()) {
+        if (!isLargeAudioFrameSupported(mComponent, supportedValues)) {
+            GTEST_SKIP() << "As component does not support large frame";
+        }
+        // time_sec * sample_rate * channel_count * 2 (bytes_per_channel)
+        mMaxOutputSize = 60 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        mOutputThresholdSize = 50 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        ASSERT_EQ(configureLargeFrameParams(mComponent, mMaxOutputSize,
+                mOutputThresholdSize, supportedValues), C2_OK);
+    }
     ASSERT_EQ(mComponent->start(), C2_OK);
 
     // request EOS for thumbnail
@@ -611,6 +793,18 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    getInputChannelInfo(mComponent, mMime, bitStreamInfo);
+    std::vector<C2FieldSupportedValues> supportedValues;
+    if (!Info.top().largeFrameInfo.empty()) {
+        if (!isLargeAudioFrameSupported(mComponent, supportedValues)) {
+            GTEST_SKIP() << "As component does not support large frame";
+        }
+        // time_sec * sample_rate * channel_count * 2 (bytes_per_channel)
+        mMaxOutputSize = 60 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        mOutputThresholdSize = 50 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        ASSERT_EQ(configureLargeFrameParams(mComponent, mMaxOutputSize,
+                mOutputThresholdSize, supportedValues), C2_OK);
+    }
     ASSERT_EQ(mComponent->start(), C2_OK);
     // flush
     std::list<std::unique_ptr<C2Work>> flushedWork;
@@ -681,6 +875,7 @@
     uint32_t flags = 0;
     uint32_t vtsFlags = 0;
     uint32_t timestamp = 0;
+    uint32_t nLargeFrames = 0;
     bool codecConfig = false;
     // This test introduces empty CSD after every 20th frame
     // and empty input frames at an interval of 5 frames.
@@ -688,6 +883,7 @@
         if (!(frameId % 5)) {
             vtsFlags = !(frameId % 20) ? (1 << VTS_BIT_FLAG_CSD_FRAME) : 0;
             bytesCount = 0;
+            Info.push_back({bytesCount, vtsFlags, timestamp, {}});
         } else {
             if (!(eleInfo >> bytesCount)) break;
             eleInfo >> flags;
@@ -695,8 +891,20 @@
             ASSERT_NE(vtsFlags, 0xFF) << "unrecognized flag entry in info file: " << mInfoFile;
             eleInfo >> timestamp;
             codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
+            Info.push_back({bytesCount, vtsFlags, timestamp, {}});
+            if ((vtsFlags & (1 << VTS_BIT_FLAG_LARGE_AUDIO_FRAME)) != 0) {
+                eleInfo >> nLargeFrames;
+                // this is a large audio frame.
+                while(nLargeFrames-- > 0) {
+                    eleInfo >> bytesCount;
+                    eleInfo >> flags;
+                    eleInfo >> timestamp;
+                    vtsFlags = mapInfoFlagstoVtsFlags(flags);
+                    Info.editItemAt(Info.size() - 1).largeFrameInfo.push_back(
+                            {(uint32_t)bytesCount, vtsFlags, timestamp});
+                }
+            }
         }
-        Info.push_back({bytesCount, vtsFlags, timestamp});
         frameId++;
     }
     eleInfo.close();
@@ -711,6 +919,18 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
+    getInputChannelInfo(mComponent, mMime, bitStreamInfo);
+    std::vector<C2FieldSupportedValues> supportedValues;
+    if (!Info.top().largeFrameInfo.empty()) {
+        if (!isLargeAudioFrameSupported(mComponent, supportedValues)) {
+            GTEST_SKIP() << "As component does not support large frame";
+        }
+        // time_sec * sample_rate * channel_count * 2 (bytes_per_channel)
+        mMaxOutputSize = 60 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        mOutputThresholdSize = 50 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        ASSERT_EQ(configureLargeFrameParams(mComponent, mMaxOutputSize,
+                mOutputThresholdSize, supportedValues), C2_OK);
+    }
     ASSERT_EQ(mComponent->start(), C2_OK);
     eleStream.open(mInputFile, std::ifstream::binary);
     ASSERT_EQ(eleStream.is_open(), true);
@@ -766,7 +986,18 @@
         std::cout << "[   WARN   ] Test Skipped \n";
         return;
     }
-
+    getInputChannelInfo(mComponent, mMime, bitStreamInfo);
+    std::vector<C2FieldSupportedValues> supportedValues;
+    if (!Info.top().largeFrameInfo.empty()) {
+        if (!isLargeAudioFrameSupported(mComponent, supportedValues)) {
+            GTEST_SKIP() << "As component does not support large frame";
+        }
+        // time_sec * sample_rate * channel_count * 2 (bytes_per_channel)
+        mMaxOutputSize = 60 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        mOutputThresholdSize = 50 * bitStreamInfo[0] * bitStreamInfo[1] * 2;
+        ASSERT_EQ(configureLargeFrameParams(mComponent, mMaxOutputSize,
+                mOutputThresholdSize, supportedValues), C2_OK);
+    }
     ASSERT_EQ(mComponent->start(), C2_OK);
     std::ifstream eleStream;
     eleStream.open(mInputFile, std::ifstream::binary);
@@ -864,4 +1095,4 @@
     ::testing::InitGoogleTest(&argc, argv);
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
-}
+}
\ No newline at end of file
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
index 6c04683..9b9c62f 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
+++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -38,6 +38,8 @@
         <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
         <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
         <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
+        <option name="push-file" key="bbb_raw_1ch_8khz_s32le_largeframe.info"
+                value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le_largeframe.info" />
         <option name="push-file" key="bbb_raw_1ch_8khz_s32le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.raw" />
         <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.info" />
         <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index a72f7bd..92b0bf5 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -235,12 +235,13 @@
     uint32_t flags = 0;
     uint32_t vtsFlags = 0;
     uint32_t timestamp = 0;
+    uint32_t nLargeFrames = 0;
     while (1) {
         if (!(eleInfo >> bytesCount)) break;
         eleInfo >> flags;
         vtsFlags = mapInfoFlagstoVtsFlags(flags);
         if (vtsFlags == 0xFF) {
-            ALOGE("unrecognized flag entry in info file %s", info.c_str());
+            ALOGE("unrecognized flag(0x%x) entry in info file %s", flags, info.c_str());
             return -1;
         }
         eleInfo >> timestamp;
@@ -250,7 +251,18 @@
         if (timestampDevTest && !codecConfig && !nonDisplayFrame) {
             timestampUslist->push_back(timestamp);
         }
-        frameInfo->push_back({bytesCount, vtsFlags, timestamp});
+        frameInfo->push_back({bytesCount, vtsFlags, timestamp, {}});
+        if (vtsFlags & (1 << VTS_BIT_FLAG_LARGE_AUDIO_FRAME)) {
+            eleInfo >> nLargeFrames;
+            while(nLargeFrames-- > 0) {
+                eleInfo >> bytesCount;
+                eleInfo >> flags;
+                eleInfo >> timestamp;
+                vtsFlags = mapInfoFlagstoVtsFlags(flags);
+                frameInfo->editItemAt(frameInfo->size() - 1).largeFrameInfo.push_back(
+                        {vtsFlags, static_cast<uint32_t>(bytesCount), timestamp});
+            }
+        }
     }
     ALOGV("numCsds : %d", numCsds);
     eleInfo.close();
@@ -285,5 +297,6 @@
     else if (infoFlags == 0x1) return (1 << VTS_BIT_FLAG_SYNC_FRAME);
     else if (infoFlags == 0x10) return (1 << VTS_BIT_FLAG_NO_SHOW_FRAME);
     else if (infoFlags == 0x20) return (1 << VTS_BIT_FLAG_CSD_FRAME);
+    else if (infoFlags == 0x40) return (1 << VTS_BIT_FLAG_LARGE_AUDIO_FRAME);
     return 0xFF;
 }
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index eda7b99..708fe15 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -54,12 +54,16 @@
     VTS_BIT_FLAG_SYNC_FRAME = 1,
     VTS_BIT_FLAG_NO_SHOW_FRAME = 2,
     VTS_BIT_FLAG_CSD_FRAME = 3,
+    VTS_BIT_FLAG_LARGE_AUDIO_FRAME = 4,
 };
 
 struct FrameInfo {
     int bytesCount;
     uint32_t vtsFlags;
     int64_t timestamp;
+    // This is used when access-units are marked with
+    // VTS_BIT_FLAG_LARGE_AUDIO_FRAME
+    std::vector<C2AccessUnitInfosStruct> largeFrameInfo;
 };
 
 template <typename... T>
@@ -86,7 +90,6 @@
     virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component>& comp,
                             std::list<std::unique_ptr<C2Work>>& workItems) override {
         /* TODO */
-        ALOGD("onWorkDone called");
         (void)comp;
         if (callBack) callBack(workItems);
     }
@@ -103,7 +106,6 @@
                          uint32_t errorCode) override {
         /* TODO */
         (void)comp;
-        ALOGD("onError called");
         if (errorCode != 0) ALOGE("Error : %u", errorCode);
     }
 
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_raw_1ch_8khz_s32le_largeframe.info b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_raw_1ch_8khz_s32le_largeframe.info
new file mode 100644
index 0000000..291e323
--- /dev/null
+++ b/media/codec2/hal/hidl/1.0/vts/functional/res/bbb_raw_1ch_8khz_s32le_largeframe.info
@@ -0,0 +1,5 @@
+16384 64 0 		 1 16384 1 0
+49152 64 1024000 3 16384 1 1024000 16384 1 2048000 16384 1 3072000
+32768 64 4096000 2 16384 1 4096000 16384 1 5120000
+49152 64 6144000 3 16384 1 6144000 16384 1 7168000 16384 1 8192000
+10924 64 9216000 1 10924 1 9216000
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index df89510..f8fd425 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -739,7 +739,7 @@
             ASSERT_NE(vtsFlags, 0xFF) << "unrecognized flag entry in info file: " << mInfoFile;
             eleInfo >> timestamp;
             timestamp += timestampOffset;
-            Info.push_back({bytesCount, vtsFlags, timestamp});
+            Info.push_back({bytesCount, vtsFlags, timestamp, {}});
             bool codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
             bool nonDisplayFrame = (vtsFlags & (1 << VTS_BIT_FLAG_NO_SHOW_FRAME)) != 0;
 
@@ -978,7 +978,7 @@
             eleInfo >> timestamp;
             codecConfig = (vtsFlags & (1 << VTS_BIT_FLAG_CSD_FRAME)) != 0;
         }
-        Info.push_back({bytesCount, vtsFlags, timestamp});
+        Info.push_back({bytesCount, vtsFlags, timestamp, {}});
         frameId++;
     }
     eleInfo.close();
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index fc3f699..2af18cc 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -974,7 +974,7 @@
     if (mModule == nullptr) return NO_INIT;
     {
         std::lock_guard l(mLock);
-        mMapper.resetUnusedPatchesAndPortConfigs();
+        mMapper.resetUnusedPatchesPortConfigsAndPorts();
     }
     ModuleDebug debug{ .simulateDeviceConnections = enabled };
     status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index d4024a2..2b7f298 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -730,7 +730,7 @@
             this, __func__, ioHandle, device.toString().c_str(),
             flags.toString().c_str(), toString(source).c_str(),
             config->toString().c_str(), mixPortConfig->toString().c_str());
-    resetUnusedPatchesAndPortConfigs();
+    resetUnusedPatchesPortConfigsAndPorts();
     const AudioConfig initialConfig = *config;
     // Find / create AudioPortConfigs for the device port and the mix port,
     // then find / create a patch between them, and open a stream on the mix port.
@@ -858,7 +858,7 @@
             result = BAD_VALUE;
         }
     }
-    resetUnusedPortConfigs();
+    resetUnusedPortConfigsAndPorts();
     return result;
 }
 
@@ -875,7 +875,7 @@
     ALOGE("%s: port config id %d not found", __func__, portConfigId);
 }
 
-void Hal2AidlMapper::resetUnusedPatchesAndPortConfigs() {
+void Hal2AidlMapper::resetUnusedPatchesPortConfigsAndPorts() {
     // Since patches can be created independently of streams via 'createOrUpdatePatch',
     // here we only clean up patches for released streams.
     std::set<int32_t> patchesToRelease;
@@ -889,11 +889,11 @@
             it = mStreams.erase(it);
         }
     }
-    // 'releaseAudioPatches' also resets unused port configs.
+    // 'releaseAudioPatches' also resets unused port configs and ports.
     releaseAudioPatches(patchesToRelease);
 }
 
-void Hal2AidlMapper::resetUnusedPortConfigs() {
+void Hal2AidlMapper::resetUnusedPortConfigsAndPorts() {
     // The assumption is that port configs are used to create patches
     // (or to open streams, but that involves creation of patches, too). Thus,
     // orphaned port configs can and should be reset.
@@ -934,6 +934,7 @@
 }
 
 status_t Hal2AidlMapper::setDevicePortConnectedState(const AudioPort& devicePort, bool connected) {
+    resetUnusedPatchesPortConfigsAndPorts();
     if (connected) {
         AudioDevice matchDevice = devicePort.ext.get<AudioPortExt::device>().device;
         std::optional<AudioPort> templatePort;
@@ -968,7 +969,6 @@
             }
             templatePort = portsIt->second;
         }
-        resetUnusedPatchesAndPortConfigs();
 
         // Use the ID of the "template" port, use all the information from the provided port.
         AudioPort connectedPort = devicePort;
@@ -995,7 +995,6 @@
             ALOGD("%s: device port for device %s found in the module %s",
                     __func__, matchDevice.toString().c_str(), mInstance.c_str());
         }
-        resetUnusedPatchesAndPortConfigs();
 
         // Disconnection of remote submix out with address "0" is a special case. We need to replace
         // the connected port entry with the "augmented template".
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.h b/media/libaudiohal/impl/Hal2AidlMapper.h
index 93ce233..f937173 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.h
+++ b/media/libaudiohal/impl/Hal2AidlMapper.h
@@ -91,7 +91,7 @@
         ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
         Cleanups* cleanups = nullptr);
     status_t releaseAudioPatch(int32_t patchId);
-    void resetUnusedPatchesAndPortConfigs();
+    void resetUnusedPatchesPortConfigsAndPorts();
     status_t setDevicePortConnectedState(
             const ::aidl::android::media::audio::common::AudioPort& devicePort, bool connected);
 
@@ -184,7 +184,7 @@
     status_t releaseAudioPatches(const std::set<int32_t>& patchIds);
     void resetPatch(int32_t patchId) { (void)releaseAudioPatch(patchId); }
     void resetPortConfig(int32_t portConfigId);
-    void resetUnusedPortConfigs();
+    void resetUnusedPortConfigsAndPorts();
     status_t updateAudioPort(
             int32_t portId, ::aidl::android::media::audio::common::AudioPort* port);
     status_t updateRoutes();
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index c2d7ee1..5f525d7 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -234,7 +234,9 @@
     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    return mStream->dump(fd, Args(args).args(), args.size());
+    status_t status = mStream->dump(fd, Args(args).args(), args.size());
+    mStreamPowerLog.dump(fd);
+    return status;
 }
 
 status_t StreamHalAidl::start() {
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index 37633ae..b56872c 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -69,6 +69,6 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 9e154cf..e93a4e6 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -95,6 +95,6 @@
     ],
 
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index cc19a80..7d96b53 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -84,6 +84,6 @@
     ],
 
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index 05bbec3..46e4669 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -69,6 +69,6 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index da5346f..a50ba93 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -130,7 +130,7 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
 
@@ -161,6 +161,6 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index 564eb36..994b061 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -89,6 +89,6 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index a8b665b..66ceadf 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -70,6 +70,6 @@
     ],
     relative_install_path: "soundfx",
     visibility: [
-        "//hardware/interfaces/audio/aidl/default",
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
     ],
 }
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 0af9d12..712b405 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -137,7 +137,7 @@
             cflags: [
                 "-DDISABLE_AUDIO_SYSTEM_OFFLOAD",
             ],
-        }
+        },
     },
 }
 
@@ -273,7 +273,7 @@
         "VideoFrameSchedulerBase.cpp",
         "VideoFrameScheduler.cpp",
         "VideoRenderQualityTracker.cpp",
-      ],
+    ],
 
     shared_libs: [
         "libstagefright_framecapture_utils",
@@ -330,7 +330,7 @@
         "libmedia_ndkformatpriv",
     ],
 
-    header_libs:[
+    header_libs: [
         "libmediadrm_headers",
         "libnativeloader-headers",
         "libstagefright_xmlparser_headers",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index c27cfc5..6aac0e5 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -320,8 +320,8 @@
                 return Status::fromStatus(STATUS_INVALID_OPERATION);
             }
             ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(this)};
+                                        .uid = static_cast<int32_t>(mUid),
+                                        .id = getId(this)};
             service->removeClient(clientInfo);
             *_aidl_return = true;
             return Status::ok();
@@ -398,6 +398,10 @@
         mCodecName = name;
     }
 
+    inline void setImportance(int importance) {
+        mImportance = importance;
+    }
+
 private:
     // To get the binder interface to ResourceManagerService.
     void getService() {
@@ -437,12 +441,30 @@
         mGetServiceFuture = std::async(std::launch::async, [this] { getService(); });
     }
 
+    /**
+     * Get the ClientInfo to communicate with the ResourceManager.
+     *
+     * ClientInfo includes:
+     *   - {pid, uid} of the process
+     *   - identifier for the client
+     *   - name of the client/codec
+     *   - importance associated with the client
+     */
+    inline ClientInfoParcel getClientInfo() const {
+        ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                    .uid = static_cast<int32_t>(mUid),
+                                    .id = getId(mClient),
+                                    .name = mCodecName,
+                                    .importance = mImportance};
+        return std::move(clientInfo);
+    }
 
 private:
-    std::mutex mLock;
-    pid_t mPid;
-    uid_t mUid;
-    bool mBinderDied = false;
+    std::mutex  mLock;
+    bool        mBinderDied = false;
+    pid_t       mPid;
+    uid_t       mUid;
+    int         mImportance = 0;
     std::string mCodecName;
     /**
      * Reconnecting with the ResourceManagerService, after its binder interface dies,
@@ -550,11 +572,7 @@
     std::vector<MediaResourceParcel> resources;
     std::copy(mMediaResourceParcel.begin(), mMediaResourceParcel.end(),
               std::back_inserter(resources));
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    mService->addResource(clientInfo, mClient, resources);
+    mService->addResource(getClientInfo(), mClient, resources);
 }
 
 void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
@@ -587,11 +605,7 @@
     }
     std::vector<MediaResourceParcel> resources;
     resources.push_back(resource);
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    service->addResource(clientInfo, mClient, resources);
+    service->addResource(getClientInfo(), mClient, resources);
     mMediaResourceParcel.emplace(resource);
 }
 
@@ -605,11 +619,7 @@
     }
     std::vector<MediaResourceParcel> resources;
     resources.push_back(resource);
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    service->removeResource(clientInfo, resources);
+    service->removeResource(getClientInfo(), resources);
     mMediaResourceParcel.erase(resource);
 }
 
@@ -620,11 +630,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    service->removeClient(clientInfo);
+    service->removeClient(getClientInfo());
     mMediaResourceParcel.clear();
 }
 
@@ -635,11 +641,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    service->markClientForPendingRemoval(clientInfo);
+    service->markClientForPendingRemoval(getClientInfo());
     mMediaResourceParcel.clear();
 }
 
@@ -652,11 +654,7 @@
         return false;
     }
     bool success;
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    Status status = service->reclaimResource(clientInfo, resources, &success);
+    Status status = service->reclaimResource(getClientInfo(), resources, &success);
     return status.isOk() && success;
 }
 
@@ -667,11 +665,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
-                                .uid = static_cast<int32_t>(mUid),
-                                .id = getId(mClient),
-                                .name = mCodecName};
-    service->notifyClientCreated(clientInfo);
+    service->notifyClientCreated(getClientInfo());
 }
 
 void MediaCodec::ResourceManagerServiceProxy::notifyClientStarted(
@@ -682,10 +676,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    clientConfig.clientInfo.pid = static_cast<int32_t>(mPid);
-    clientConfig.clientInfo.uid = static_cast<int32_t>(mUid);
-    clientConfig.clientInfo.id = getId(mClient);
-    clientConfig.clientInfo.name = mCodecName;
+    clientConfig.clientInfo = getClientInfo();
     service->notifyClientStarted(clientConfig);
 }
 
@@ -697,10 +688,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    clientConfig.clientInfo.pid = static_cast<int32_t>(mPid);
-    clientConfig.clientInfo.uid = static_cast<int32_t>(mUid);
-    clientConfig.clientInfo.id = getId(mClient);
-    clientConfig.clientInfo.name = mCodecName;
+    clientConfig.clientInfo = getClientInfo();
     service->notifyClientStopped(clientConfig);
 }
 
@@ -712,10 +700,7 @@
         ALOGW("Service isn't available");
         return;
     }
-    clientConfig.clientInfo.pid = static_cast<int32_t>(mPid);
-    clientConfig.clientInfo.uid = static_cast<int32_t>(mUid);
-    clientConfig.clientInfo.id = getId(mClient);
-    clientConfig.clientInfo.name = mCodecName;
+    clientConfig.clientInfo = getClientInfo();
     service->notifyClientConfigChanged(clientConfig);
 }
 
@@ -1716,6 +1701,21 @@
     }
 }
 
+void MediaCodec::updateCodecImportance(const sp<AMessage>& msg) {
+    // Update the codec importance.
+    int32_t importance = 0;
+    if (msg->findInt32(KEY_IMPORTANCE, &importance)) {
+        // Ignoring the negative importance.
+        if (importance >= 0) {
+            // Notify RM about the change in the importance.
+            mResourceManagerProxy->setImportance(importance);
+            ClientConfigParcel clientConfig;
+            initClientConfigParcel(clientConfig);
+            mResourceManagerProxy->notifyClientConfigChanged(clientConfig);
+        }
+    }
+}
+
 constexpr const char *MediaCodec::asString(TunnelPeekState state, const char *default_string){
     switch(state) {
         case TunnelPeekState::kLegacyMode:
@@ -2224,23 +2224,9 @@
 static void mapFormat(AString componentName, const sp<AMessage> &format, const char *kind,
                       bool reverse);
 
-status_t MediaCodec::configure(
-        const sp<AMessage> &format,
-        const sp<Surface> &nativeWindow,
-        const sp<ICrypto> &crypto,
-        uint32_t flags) {
-    return configure(format, nativeWindow, crypto, NULL, flags);
-}
-
-status_t MediaCodec::configure(
-        const sp<AMessage> &format,
-        const sp<Surface> &surface,
-        const sp<ICrypto> &crypto,
-        const sp<IDescrambler> &descrambler,
-        uint32_t flags) {
-
-    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
+mediametrics_handle_t MediaCodec::createMediaMetrics(const sp<AMessage>& format, uint32_t flags) {
     mediametrics_handle_t nextMetricsHandle = mediametrics_create(kCodecKeyName);
+    bool isEncoder = (flags & CONFIGURE_FLAG_ENCODE);
 
     // TODO: validity check log-session-id: it should be a 32-hex-digit.
     format->findString("log-session-id", &mLogSessionId);
@@ -2255,8 +2241,7 @@
         if (format->findInt32("level", &level)) {
             mediametrics_setInt32(nextMetricsHandle, kCodecLevel, level);
         }
-        mediametrics_setInt32(nextMetricsHandle, kCodecEncoder,
-                              (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
+        mediametrics_setInt32(nextMetricsHandle, kCodecEncoder, isEncoder);
 
         if (!mLogSessionId.empty()) {
             mediametrics_setCString(nextMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str());
@@ -2335,7 +2320,7 @@
         }
     }
 
-    if (flags & CONFIGURE_FLAG_ENCODE) {
+    if (isEncoder) {
         int8_t enableShaping = property_get_bool(enableMediaFormatShapingProperty,
                                                  enableMediaFormatShapingDefault);
         if (!enableShaping) {
@@ -2380,6 +2365,31 @@
 
     updateLowLatency(format);
 
+    return nextMetricsHandle;
+}
+
+status_t MediaCodec::configure(
+        const sp<AMessage> &format,
+        const sp<Surface> &nativeWindow,
+        const sp<ICrypto> &crypto,
+        uint32_t flags) {
+    return configure(format, nativeWindow, crypto, NULL, flags);
+}
+
+status_t MediaCodec::configure(
+        const sp<AMessage> &format,
+        const sp<Surface> &surface,
+        const sp<ICrypto> &crypto,
+        const sp<IDescrambler> &descrambler,
+        uint32_t flags) {
+
+    // Update the codec importance.
+    updateCodecImportance(format);
+
+    // Create and set up metrics for this codec.
+    mediametrics_handle_t nextMetricsHandle = createMediaMetrics(format, flags);
+
+    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
     msg->setMessage("format", format);
     msg->setInt32("flags", flags);
     msg->setObject("surface", surface);
@@ -6591,6 +6601,7 @@
         return NO_INIT;
     }
     updateLowLatency(params);
+    updateCodecImportance(params);
     mapFormat(mComponentName, params, nullptr, false);
     updateTunnelPeek(params);
     mCodec->signalSetParameters(params);
diff --git a/media/libstagefright/colorconversion/fuzzer/Android.bp b/media/libstagefright/colorconversion/fuzzer/Android.bp
index 76b054a..237e715 100644
--- a/media/libstagefright/colorconversion/fuzzer/Android.bp
+++ b/media/libstagefright/colorconversion/fuzzer/Android.bp
@@ -47,9 +47,15 @@
     ],
     fuzz_config: {
         cc: [
-            "android-media-fuzzing-reports@google.com",
+            "android-fwk-video@google.com",
         ],
-        componentid: 155276,
+        componentid: 42195,
+        hotlists: ["4593311"],
+        description: "The fuzzer targets the APIs of libstagefright_color_conversion",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index baa5b7e..2f94e5e 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -320,6 +320,9 @@
     status_t reclaim(bool force = false);
     friend struct ResourceManagerClient;
 
+    // to create the metrics associated with this codec.
+    mediametrics_handle_t createMediaMetrics(const sp<AMessage>& format, uint32_t flags);
+
 private:
     enum State {
         UNINITIALIZED,
@@ -462,6 +465,7 @@
     void resetMetricsFields();
     void updateEphemeralMediametrics(mediametrics_handle_t item);
     void updateLowLatency(const sp<AMessage> &msg);
+    void updateCodecImportance(const sp<AMessage>& msg);
     void onGetMetrics(const sp<AMessage>& msg);
     constexpr const char *asString(TunnelPeekState state, const char *default_string="?");
     void updateTunnelPeek(const sp<AMessage> &msg);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 7334639..f4c40e1 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -794,6 +794,7 @@
 inline constexpr char KEY_HDR10_PLUS_INFO[] = "hdr10-plus-info";
 inline constexpr char KEY_HEIGHT[] = "height";
 inline constexpr char KEY_I_FRAME_INTERVAL[] = "i-frame-interval";
+inline constexpr char KEY_IMPORTANCE[] = "importance";
 inline constexpr char KEY_INTRA_REFRESH_PERIOD[] = "intra-refresh-period";
 inline constexpr char KEY_IS_ADTS[] = "is-adts";
 inline constexpr char KEY_IS_AUTOSELECT[] = "is-autoselect";
@@ -809,6 +810,9 @@
 inline constexpr char KEY_MAX_FPS_TO_ENCODER[] = "max-fps-to-encoder";
 inline constexpr char KEY_MAX_HEIGHT[] = "max-height";
 inline constexpr char KEY_MAX_INPUT_SIZE[] = "max-input-size";
+inline constexpr char KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE[] = "buffer-batch-max-output-size";
+inline constexpr char KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE[] =
+        "buffer-batch-threshold-output-size";
 inline constexpr char KEY_MAX_OUTPUT_CHANNEL_COUNT[] = "max-output-channel-count";
 inline constexpr char KEY_MAX_PTS_GAP_TO_ENCODER[] = "max-pts-gap-to-encoder";
 inline constexpr char KEY_MAX_WIDTH[] = "max-width";
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockHandle.h b/media/mtp/tests/MtpFuzzer/MtpMockHandle.h
index 111485c..aa632a4 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockHandle.h
+++ b/media/mtp/tests/MtpFuzzer/MtpMockHandle.h
@@ -45,18 +45,18 @@
                   pkt.size());
 
             // packet is bigger than what the caller can handle,
-            if (pkt.size() > len) {
+            if (pkt.size() - mPacketOffset > len) {
                 memcpy(data, pkt.data() + mPacketOffset, len);
 
                 mPacketOffset += len;
                 readAmt = len;
                 // packet is equal or smaller than the caller buffer
             } else {
-                memcpy(data, pkt.data() + mPacketOffset, pkt.size());
+                memcpy(data, pkt.data() + mPacketOffset, pkt.size() - mPacketOffset);
 
                 mPacketNumber++;
                 mPacketOffset = 0;
-                readAmt = pkt.size();
+                readAmt = pkt.size() - mPacketOffset;
             }
 
             return readAmt;
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 161b5e3..a26681e 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -428,6 +428,7 @@
 EXPORT const char* AMEDIAFORMAT_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
 EXPORT const char* AMEDIAFORMAT_KEY_HEIGHT = "height";
 EXPORT const char* AMEDIAFORMAT_KEY_ICC_PROFILE = "icc-profile";
+EXPORT const char* AMEDIAFORMAT_KEY_IMPORTANCE = "importance";
 EXPORT const char* AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_ADTS = "is-adts";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_AUTOSELECT = "is-autoselect";
@@ -449,6 +450,10 @@
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
+EXPORT const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE =
+        "buffer-batch-max-output-size";
+EXPORT const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE =
+        "buffer-batch-threshold-output-size";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_PTS_GAP_TO_ENCODER = "max-pts-gap-to-encoder";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
 EXPORT const char* AMEDIAFORMAT_KEY_MIME = "mime";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index b2cdf8d..cc1dd9f 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -168,6 +168,7 @@
 extern const char* AMEDIAFORMAT_KEY_GRID_ROWS __INTRODUCED_IN(28);
 extern const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO __INTRODUCED_IN(28);
 extern const char* AMEDIAFORMAT_KEY_HEIGHT __INTRODUCED_IN(21);
+extern const char* AMEDIAFORMAT_KEY_IMPORTANCE __INTRODUCED_IN(35);
 extern const char* AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD __INTRODUCED_IN(28);
 extern const char* AMEDIAFORMAT_KEY_IS_ADTS __INTRODUCED_IN(21);
 extern const char* AMEDIAFORMAT_KEY_IS_AUTOSELECT __INTRODUCED_IN(21);
@@ -186,6 +187,8 @@
 extern const char* AMEDIAFORMAT_KEY_MAX_B_FRAMES __INTRODUCED_IN(34);
 extern const char* AMEDIAFORMAT_KEY_MAX_HEIGHT __INTRODUCED_IN(21);
 extern const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE __INTRODUCED_IN(21);
+extern const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE __INTRODUCED_IN(35);
+extern const char* AMEDIAFORMAT_KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE __INTRODUCED_IN(35);
 extern const char* AMEDIAFORMAT_KEY_MAX_WIDTH __INTRODUCED_IN(21);
 extern const char* AMEDIAFORMAT_KEY_MIME __INTRODUCED_IN(21);
 extern const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA __INTRODUCED_IN(28);
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 794bda0..7f66859 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -74,6 +74,7 @@
     name: "libresourcemanagerservice",
 
     srcs: [
+        "ClientImportanceReclaimPolicy.cpp",
         "DefaultResourceModel.cpp",
         "ProcessPriorityReclaimPolicy.cpp",
         "ResourceManagerMetrics.cpp",
diff --git a/services/mediaresourcemanager/ClientImportanceReclaimPolicy.cpp b/services/mediaresourcemanager/ClientImportanceReclaimPolicy.cpp
new file mode 100644
index 0000000..a81b32f
--- /dev/null
+++ b/services/mediaresourcemanager/ClientImportanceReclaimPolicy.cpp
@@ -0,0 +1,88 @@
+/*
+**
+** Copyright 2023, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClientImportanceReclaimPolicy"
+#include <utils/Log.h>
+
+#include "ResourceTracker.h"
+#include "ResourceManagerService.h"
+#include "ClientImportanceReclaimPolicy.h"
+
+namespace android {
+
+using aidl::android::media::IResourceManagerClient;
+
+ClientImportanceReclaimPolicy::ClientImportanceReclaimPolicy(
+        const std::shared_ptr<ResourceTracker>& resourceTracker)
+    : mResourceTracker(resourceTracker) {
+}
+
+ClientImportanceReclaimPolicy::~ClientImportanceReclaimPolicy() {
+}
+
+// Find the biggest client from the same process with the lowest importance
+// than that of the requesting client.
+bool ClientImportanceReclaimPolicy::getClients(const ReclaimRequestInfo& reclaimRequestInfo,
+                                              const std::vector<ClientInfo>& clients,
+                                              std::vector<ClientInfo>& targetClients) {
+    pid_t callingPid = reclaimRequestInfo.mCallingPid;
+    int32_t callingImportance = reclaimRequestInfo.mCallingClientImportance;
+    MediaResource::Type type = reclaimRequestInfo.mResources[0].type;
+    MediaResource::SubType subType = reclaimRequestInfo.mResources[0].subType;
+    ClientInfo targetClient;
+    // Look to find the biggest client with lowest importance from the same process that
+    // has the other resources and with the given primary type.
+    bool found = false;
+    MediaResource::SubType primarySubType = subType;
+    for (size_t index = 1; !found && (index < reclaimRequestInfo.mResources.size()); index++) {
+        MediaResource::Type type = reclaimRequestInfo.mResources[index].type;
+        MediaResource::SubType subType = reclaimRequestInfo.mResources[index].subType;
+        found = mResourceTracker->getLeastImportantBiggestClient(
+            callingPid, callingImportance,
+            type, subType, primarySubType,
+            clients, targetClient);
+    }
+    // If no success, then select the biggest client of primary type with lowest importance
+    // from the same process.
+    if (!found) {
+        found = mResourceTracker->getLeastImportantBiggestClient(
+            callingPid, callingImportance,
+            type, subType, MediaResource::SubType::kUnspecifiedSubType,
+            clients, targetClient);
+    }
+    // If we haven't found a client yet, then select the biggest client of different type
+    // with lowest importance from the same process.
+    // This is applicable for codec type only.
+    if (!found) {
+        if (type != MediaResource::Type::kSecureCodec &&
+            type != MediaResource::Type::kNonSecureCodec) {
+            return false;
+        }
+        MediaResourceType otherType = (type == MediaResource::Type::kSecureCodec) ?
+            MediaResource::Type::kNonSecureCodec : MediaResource::Type::kSecureCodec;
+        if (!mResourceTracker->getLeastImportantBiggestClient(
+            callingPid, callingImportance,
+            otherType, subType, MediaResource::SubType::kUnspecifiedSubType,
+            clients, targetClient)) {
+            return false;
+        }
+    }
+    targetClients.emplace_back(targetClient);
+    return true;
+}
+} // namespace android
diff --git a/services/mediaresourcemanager/ClientImportanceReclaimPolicy.h b/services/mediaresourcemanager/ClientImportanceReclaimPolicy.h
new file mode 100644
index 0000000..1a54c7d
--- /dev/null
+++ b/services/mediaresourcemanager/ClientImportanceReclaimPolicy.h
@@ -0,0 +1,64 @@
+/*
+**
+** Copyright 2023, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_MEDIA_CLIENTIMPORTANCERECLAIMPOLICY_H_
+#define ANDROID_MEDIA_CLIENTIMPORTANCERECLAIMPOLICY_H_
+
+#include <media/MediaResource.h>
+#include "IReclaimPolicy.h"
+
+namespace android {
+
+class ResourceTracker;
+struct ClientInfo;
+
+/*
+ * Implementation of Reclaim Policy based on the client's importance.
+ *
+ * Find the least important (other than that of requesting client) client from the
+ * same process (that is requesting for the resource).
+ * If there are multiple clients with least importance, then pick the biggest
+ * client among them.
+ *
+ */
+class ClientImportanceReclaimPolicy : public IReclaimPolicy {
+public:
+    explicit ClientImportanceReclaimPolicy(const std::shared_ptr<ResourceTracker>& resourceTracker);
+
+    virtual ~ClientImportanceReclaimPolicy();
+
+    /*
+     * Based on the client importance, identify and return the least important client of
+     * the requesting process from the list of given clients that satisfy the resource requested.
+     *
+     * @param[in]  reclaimRequestInfo Information about the resource request
+     * @param[in]  client List of clients to select from.
+     * @param[out] targetClients Upon success, this will have the list of identified client(s).
+     *
+     * @return true on success, false otherwise
+     */
+    bool getClients(const ReclaimRequestInfo& reclaimRequestInfo,
+                    const std::vector<ClientInfo>& clients,
+                    std::vector<ClientInfo>& targetClients) override;
+
+private:
+    std::shared_ptr<ResourceTracker> mResourceTracker;
+};
+
+} // namespace android
+
+#endif  // ANDROID_MEDIA_CLIENTIMPORTANCERECLAIMPOLICY_H_
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 4bdb6e1..3a02443 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -74,10 +74,7 @@
 
             const ResourceList& resources = info.resources;
             resourceLog.append("        Resources:\n");
-            for (auto it = resources.begin(); it != resources.end(); it++) {
-                snprintf(buffer, SIZE, "          %s\n", toString(it->second).c_str());
-                resourceLog.append(buffer);
-            }
+            resourceLog.append(resources.toString());
         }
     }
 
@@ -315,31 +312,21 @@
 
     for (size_t i = 0; i < resources.size(); ++i) {
         const auto &res = resources[i];
-        const auto resType = std::tuple(res.type, res.subType, res.id);
 
         if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
             ALOGW("Ignoring request to remove negative value of non-drm resource");
             continue;
         }
-        if (info.resources.find(resType) == info.resources.end()) {
-            if (res.value <= 0) {
-                // We can't init a new entry with negative value, although it's allowed
-                // to merge in negative values after the initial add.
-                ALOGW("Ignoring request to add new resource entry with value <= 0");
-                continue;
-            }
+        bool isNewEntry = false;
+        if (!info.resources.add(res, &isNewEntry)) {
+            continue;
+        }
+        if (isNewEntry) {
             onFirstAdded(res, info.uid);
-            info.resources[resType] = res;
-        } else {
-            mergeResources(info.resources[resType], res);
         }
+
         // Add it to the list of added resources for observers.
-        auto it = resourceAdded.find(resType);
-        if (it == resourceAdded.end()) {
-            resourceAdded[resType] = res;
-        } else {
-            mergeResources(it->second, res);
-        }
+        resourceAdded.add(res);
     }
     if (info.deathNotifier == nullptr && client != nullptr) {
         info.deathNotifier = DeathNotifier::Create(
@@ -386,31 +373,22 @@
     ResourceList resourceRemoved;
     for (size_t i = 0; i < resources.size(); ++i) {
         const auto &res = resources[i];
-        const auto resType = std::tuple(res.type, res.subType, res.id);
 
         if (res.value < 0) {
             ALOGW("Ignoring request to remove negative value of resource");
             continue;
         }
-        // ignore if we don't have it
-        if (info.resources.find(resType) != info.resources.end()) {
-            MediaResourceParcel &resource = info.resources[resType];
+
+        long removedEntryValue = -1;
+        if (info.resources.remove(res, &removedEntryValue)) {
             MediaResourceParcel actualRemoved = res;
-            if (resource.value > res.value) {
-                resource.value -= res.value;
-            } else {
+            if (removedEntryValue != -1) {
                 onLastRemoved(res, info.uid);
-                actualRemoved.value = resource.value;
-                info.resources.erase(resType);
+                actualRemoved.value = removedEntryValue;
             }
 
             // Add it to the list of removed resources for observers.
-            auto it = resourceRemoved.find(resType);
-            if (it == resourceRemoved.end()) {
-                resourceRemoved[resType] = actualRemoved;
-            } else {
-                mergeResources(it->second, actualRemoved);
-            }
+            resourceRemoved.add(actualRemoved);
         }
     }
     if (mObserverService != nullptr && !resourceRemoved.empty()) {
@@ -453,8 +431,8 @@
     }
 
     const ResourceInfo& info = foundClient->second;
-    for (auto it = info.resources.begin(); it != info.resources.end(); it++) {
-        onLastRemoved(it->second, info.uid);
+    for (const MediaResourceParcel& res : info.resources.getResources()) {
+        onLastRemoved(res, info.uid);
     }
 
     // Since this client has been removed, update the metrics collector.
@@ -492,9 +470,10 @@
 }
 
 bool ResourceManagerService::getTargetClients(
-        int32_t callingPid,
+        const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources,
         std::vector<ClientInfo>& targetClients) {
+    int32_t callingPid = clientInfo.pid;
     std::scoped_lock lock{mLock};
     if (!mProcessInfo->isPidTrusted(callingPid)) {
         pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
@@ -598,10 +577,9 @@
 
 Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
-    int32_t callingPid = clientInfo.pid;
     std::string clientName = clientInfo.name;
     String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
-            callingPid, clientInfo.uid, getString(resources).c_str());
+            clientInfo.pid, clientInfo.uid, getString(resources).c_str());
     mServiceLog->add(log);
     *_aidl_return = false;
 
@@ -611,7 +589,7 @@
     }
 
     std::vector<ClientInfo> targetClients;
-    if (!getTargetClients(callingPid, resources, targetClients)) {
+    if (!getTargetClients(clientInfo, resources, targetClients)) {
         // Nothing to reclaim from.
         ALOGI("%s: There aren't any clients to reclaim from", __func__);
         return Status::ok();
@@ -642,7 +620,7 @@
     mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, targetClients, reclaimed);
 }
 
-std::shared_ptr<IResourceManagerClient> ResourceManagerService::getClient(
+std::shared_ptr<IResourceManagerClient> ResourceManagerService::getClient_l(
         int pid, const int64_t& clientId) const {
     std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
     if (found == mMap.end()) {
@@ -660,7 +638,7 @@
     return foundClient->second.client;
 }
 
-bool ResourceManagerService::removeClient(int pid, const int64_t& clientId) {
+bool ResourceManagerService::removeClient_l(int pid, const int64_t& clientId) {
     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
     if (found == mMap.end()) {
         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
@@ -687,8 +665,11 @@
     int64_t failedClientId = -1;
     int32_t failedClientPid = -1;
     for (const ClientInfo& targetClient : targetClients) {
-        std::shared_ptr<IResourceManagerClient> client = getClient(
-            targetClient.mPid, targetClient.mClientId);
+        std::shared_ptr<IResourceManagerClient> client = nullptr;
+        {
+            std::scoped_lock lock{mLock};
+            client = getClient_l(targetClient.mPid, targetClient.mClientId);
+        }
         if (client == nullptr) {
             // skip already released clients.
             continue;
@@ -710,7 +691,7 @@
 
     {
         std::scoped_lock lock{mLock};
-        bool found = removeClient(failedClientPid, failedClientId);
+        bool found = removeClient_l(failedClientPid, failedClientId);
         if (found) {
             ALOGW("Failed to reclaim resources from client with pid %d", failedClientPid);
         } else {
@@ -1056,8 +1037,7 @@
         if (pendingRemovalOnly && !info.pendingRemoval) {
             continue;
         }
-        for (auto it = resources.begin(); it != resources.end(); it++) {
-            const MediaResourceParcel &resource = it->second;
+        for (const MediaResourceParcel& resource : resources.getResources()) {
             if (hasResourceType(type, subType, resource)) {
                 if (resource.value > largestValue) {
                     largestValue = resource.value;
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index 44ed005..dc1600a 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -174,7 +174,7 @@
     // Gets the list of all the clients who own the list of specified resource type
     // and satisfy the resource model and the reclaim policy.
     virtual bool getTargetClients(
-        int32_t callingPid,
+        const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources,
         std::vector<ClientInfo>& targetClients);
 
@@ -210,11 +210,11 @@
     virtual void removeProcessInfoOverride(int pid);
 
     // Get the client for given pid and the clientId from the map
-    virtual std::shared_ptr<IResourceManagerClient> getClient(
+    virtual std::shared_ptr<IResourceManagerClient> getClient_l(
         int pid, const int64_t& clientId) const;
 
     // Remove the client for given pid and the clientId from the map
-    virtual bool removeClient(int pid, const int64_t& clientId);
+    virtual bool removeClient_l(int pid, const int64_t& clientId);
 
     // Get all the resource status for dump
     virtual void getResourceDump(std::string& resourceLog) const;
@@ -233,6 +233,12 @@
     virtual const std::map<int, ResourceInfos>& getResourceMap() const {
         return mMap;
     }
+    // enable/disable process priority based reclaim and client importance based reclaim
+    virtual void setReclaimPolicy(bool processPriority, bool clientImportance) {
+        // Implemented by the refactored/new RMService
+        (void)processPriority;
+        (void)clientImportance;
+    }
     // END: TEST only functions
 
 protected:
diff --git a/services/mediaresourcemanager/ResourceManagerServiceNew.cpp b/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
index dde389a..af093ca 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
+++ b/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
@@ -22,6 +22,7 @@
 #include <mediautils/ProcessInfo.h>
 
 #include "DefaultResourceModel.h"
+#include "ClientImportanceReclaimPolicy.h"
 #include "ProcessPriorityReclaimPolicy.h"
 #include "ResourceManagerServiceNew.h"
 #include "ResourceTracker.h"
@@ -61,8 +62,10 @@
 
 void ResourceManagerServiceNew::setUpReclaimPolicies() {
     mReclaimPolicies.clear();
-    // Process priority (oom score) as the Default reclaim policy.
-    mReclaimPolicies.push_back(std::make_unique<ProcessPriorityReclaimPolicy>(mResourceTracker));
+    // Add Reclaim policies based on:
+    // - the Process priority (oom score)
+    // - the client/codec importance.
+    setReclaimPolicy(true /* processPriority */, true /* clientImportance */);
 }
 
 Status ResourceManagerServiceNew::config(const std::vector<MediaResourcePolicyParcel>& policies) {
@@ -212,6 +215,11 @@
 
 Status ResourceManagerServiceNew::notifyClientConfigChanged(
         const ClientConfigParcel& clientConfig) {
+    {
+        // Update the ResourceTracker about the change in the configuration.
+        std::scoped_lock lock{mLock};
+        mResourceTracker->updateResource(clientConfig.clientInfo);
+    }
     return ResourceManagerService::notifyClientConfigChanged(clientConfig);
 }
 
@@ -225,9 +233,10 @@
 }
 
 bool ResourceManagerServiceNew::getTargetClients(
-        int callingPid,
+        const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources,
         std::vector<ClientInfo>& targetClients) {
+    int32_t callingPid = clientInfo.pid;
     std::scoped_lock lock{mLock};
     if (!mProcessInfo->isPidTrusted(callingPid)) {
         pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
@@ -238,7 +247,8 @@
 
     // Use the Resource Model to get a list of all the clients that hold the
     // needed/requested resources.
-    ReclaimRequestInfo reclaimRequestInfo{callingPid, resources};
+    uint32_t callingImportance = std::max(0, clientInfo.importance);
+    ReclaimRequestInfo reclaimRequestInfo{callingPid, callingImportance, resources};
     std::vector<ClientInfo> clients;
     if (!mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients)) {
         if (clients.empty()) {
@@ -246,7 +256,7 @@
                   __func__);
             return false;
         }
-        // Since there was a conflict, we need to reclaim all elements.
+        // Since there was a conflict, we need to reclaim all clients.
         targetClients = std::move(clients);
     } else {
         // Select a client among those have the needed resources.
@@ -290,7 +300,7 @@
 
     // Use the DefaultResourceModel to get all the clients with the resources requested.
     std::vector<MediaResourceParcel> resources{*resourceRequestInfo.mResource};
-    ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid, resources};
+    ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid, 0, resources};
     std::vector<ClientInfo> clients;
     mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients);
 
@@ -346,12 +356,12 @@
     return true;
 }
 
-std::shared_ptr<IResourceManagerClient> ResourceManagerServiceNew::getClient(
+std::shared_ptr<IResourceManagerClient> ResourceManagerServiceNew::getClient_l(
         int pid, const int64_t& clientId) const {
     return mResourceTracker->getClient(pid, clientId);
 }
 
-bool ResourceManagerServiceNew::removeClient(int pid, const int64_t& clientId) {
+bool ResourceManagerServiceNew::removeClient_l(int pid, const int64_t& clientId) {
     return mResourceTracker->removeClient(pid, clientId);
 }
 
@@ -359,4 +369,17 @@
     return mResourceTracker->getResourceMap();
 }
 
+void ResourceManagerServiceNew::setReclaimPolicy(bool processPriority, bool clientImportance) {
+    mReclaimPolicies.clear();
+    if (processPriority) {
+        // Process priority (oom score) as the Default reclaim policy.
+        mReclaimPolicies.push_back(std::make_unique<ProcessPriorityReclaimPolicy>(
+            mResourceTracker));
+    }
+    if (clientImportance) {
+        mReclaimPolicies.push_back(std::make_unique<ClientImportanceReclaimPolicy>(
+            mResourceTracker));
+    }
+}
+
 } // namespace android
diff --git a/services/mediaresourcemanager/ResourceManagerServiceNew.h b/services/mediaresourcemanager/ResourceManagerServiceNew.h
index 20c3d6e..0599936 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceNew.h
+++ b/services/mediaresourcemanager/ResourceManagerServiceNew.h
@@ -106,27 +106,13 @@
     // Returns false if any client belongs to a process with higher priority than the
     // calling process. The clients will remain unchanged if returns false.
     bool getTargetClients(
-        int32_t callingPid,
+        const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources,
         std::vector<ClientInfo>& targetClients) override;
 
     // Removes the pid from the override map.
     void removeProcessInfoOverride(int pid) override;
 
-    // Gets the list of all the clients who own the specified resource type.
-    // Returns false if any client belongs to a process with higher priority than the
-    // calling process. The clients will remain unchanged if returns false.
-    bool getAllClients_l(const ResourceRequestInfo& resourceRequestInfo,
-                         std::vector<ClientInfo>& clientsInfo) override;
-
-    // Gets the client who owns specified resource type from lowest possible priority process.
-    // Returns false if the calling process priority is not higher than the lowest process
-    // priority. The client will remain unchanged if returns false.
-    // This function is used only by the unit test.
-    bool getLowestPriorityBiggestClient_l(
-        const ResourceRequestInfo& resourceRequestInfo,
-        ClientInfo& clientInfo) override;
-
     // override the pid of given process
     bool overridePid_l(int32_t originalPid, int32_t newPid) override;
 
@@ -137,17 +123,12 @@
     // Get priority from process's pid
     bool getPriority_l(int pid, int* priority) const override;
 
-    // Gets lowest priority process that has the specified resource type.
-    // Returns false if failed. The output parameters will remain unchanged if failed.
-    bool getLowestPriorityPid_l(MediaResource::Type type, MediaResource::SubType subType,
-                                int* lowestPriorityPid, int* lowestPriority) override;
-
     // Get the client for given pid and the clientId from the map
-    std::shared_ptr<IResourceManagerClient> getClient(
+    std::shared_ptr<IResourceManagerClient> getClient_l(
         int pid, const int64_t& clientId) const override;
 
     // Remove the client for given pid and the clientId from the map
-    bool removeClient(int pid, const int64_t& clientId) override;
+    bool removeClient_l(int pid, const int64_t& clientId) override;
 
     // Get all the resource status for dump
     void getResourceDump(std::string& resourceLog) const override;
@@ -157,6 +138,30 @@
 
     Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid) override;
 
+    // The following utility functions are used only for testing by ResourceManagerServiceTest
+    // START: TEST only functions
+    // Gets the list of all the clients who own the specified resource type.
+    // Returns false if any client belongs to a process with higher priority than the
+    // calling process. The clients will remain unchanged if returns false.
+    bool getAllClients_l(const ResourceRequestInfo& resourceRequestInfo,
+                         std::vector<ClientInfo>& clientsInfo) override;
+
+    // Gets the client who owns specified resource type from lowest possible priority process.
+    // Returns false if the calling process priority is not higher than the lowest process
+    // priority. The client will remain unchanged if returns false.
+    bool getLowestPriorityBiggestClient_l(
+        const ResourceRequestInfo& resourceRequestInfo,
+        ClientInfo& clientInfo) override;
+
+    // Gets lowest priority process that has the specified resource type.
+    // Returns false if failed. The output parameters will remain unchanged if failed.
+    bool getLowestPriorityPid_l(MediaResource::Type type, MediaResource::SubType subType,
+                                int* lowestPriorityPid, int* lowestPriority) override;
+
+    // enable/disable process priority based reclaim and client importance based reclaim
+    void setReclaimPolicy(bool processPriority, bool clientImportance) override;
+    // END: TEST only functions
+
 private:
     std::shared_ptr<ResourceTracker> mResourceTracker;
     std::unique_ptr<IResourceModel> mDefaultResourceModel;
diff --git a/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp b/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
index cd21327..679ab13 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
+++ b/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
@@ -27,6 +27,93 @@
 
 namespace android {
 
+bool ResourceList::add(const MediaResourceParcel& res, bool* isNewEntry) {
+    // See if it's an existing entry, if so, merge it.
+    for (MediaResourceParcel& item : mResourceList) {
+        if (item.type == res.type && item.subType == res.subType && item.id == res.id) {
+            // We already have an item. Merge them and return
+            mergeResources(item, res);
+            return true;
+        }
+    }
+
+    // Since we have't found this resource yet, it is a new entry.
+    // We can't init a new entry with negative value, although it's allowed
+    // to merge in negative values after the initial add.
+    if (res.value <= 0) {
+        ALOGW("Ignoring request to add new resource entry with value <= 0");
+        return false;
+    }
+    if (isNewEntry) {
+        *isNewEntry = true;
+    }
+    mResourceList.push_back(res);
+    return true;
+}
+
+void ResourceList::addOrUpdate(const MediaResourceParcel& res) {
+    // See if it's an existing entry, just update the value.
+    for (MediaResourceParcel& item : mResourceList) {
+        if (item.type == res.type && item.subType == res.subType && item.id == res.id) {
+            item.value = res.value;
+            return;
+        }
+    }
+
+    // Add the new entry.
+    mResourceList.push_back(res);
+}
+
+bool ResourceList::remove(const MediaResourceParcel& res, long* removedEntryValue) {
+    // Make sure we have an entry for this resource.
+    for (std::vector<MediaResourceParcel>::iterator it = mResourceList.begin();
+         it != mResourceList.end(); it++) {
+        if (it->type == res.type && it->subType == res.subType && it->id == res.id) {
+            if (it->value > res.value) {
+                // Subtract the resource value by given value.
+                it->value -= res.value;
+            } else {
+                // This entry will be removed.
+                if (removedEntryValue) {
+                    *removedEntryValue = it->value;
+                }
+                mResourceList.erase(it);
+            }
+            return true;
+        }
+    }
+
+    // No such entry.
+    return false;
+}
+
+std::string ResourceList::toString() const {
+    std::string str;
+    for (const ::aidl::android::media::MediaResourceParcel& res : mResourceList) {
+        str.append(android::toString(res).c_str());
+        str.append("\n");
+    }
+
+    return std::move(str);
+}
+
+bool ResourceList::operator==(const ResourceList& rhs) const {
+    // Make sure the size is the same.
+    if (mResourceList.size() != rhs.mResourceList.size()) {
+        return false;
+    }
+
+    // Create a set from this object and check for the items from the rhs.
+    std::set<::aidl::android::media::MediaResourceParcel> lhs(
+            mResourceList.begin(), mResourceList.end());
+    for (const ::aidl::android::media::MediaResourceParcel& res : rhs.mResourceList) {
+        if (lhs.find(res) == lhs.end()) {
+            return false;
+        }
+    }
+    return true;
+}
+
 // Bunch of utility functions that looks for a specific Resource.
 // Check whether a given resource (of type and subtype) is found in given resource parcel.
 bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
@@ -53,8 +140,8 @@
 // Check whether a given resource (of type and subtype) is found in given resource list.
 bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
                      const ResourceList& resources) {
-    for (auto it = resources.begin(); it != resources.end(); it++) {
-        if (hasResourceType(type, subType, it->second)) {
+    for (const MediaResourceParcel& res : resources.getResources()) {
+        if (hasResourceType(type, subType, res)) {
             return true;
         }
     }
@@ -91,7 +178,6 @@
                                      const std::shared_ptr<IResourceManagerClient>& client,
                                      ResourceInfos& infos) {
     ResourceInfos::iterator found = infos.find(clientInfo.id);
-
     if (found == infos.end()) {
         ResourceInfo info{.pid = clientInfo.pid,
                           .uid = static_cast<uid_t>(clientInfo.uid),
@@ -99,7 +185,8 @@
                           .name = clientInfo.name.empty()? "<unknown client>" : clientInfo.name,
                           .client = client,
                           .deathNotifier = nullptr,
-                          .pendingRemoval = false};
+                          .pendingRemoval = false,
+                          .importance = static_cast<uint32_t>(std::max(0, clientInfo.importance))};
         auto [it, inserted] = infos.emplace(clientInfo.id, info);
         found = it;
     }
diff --git a/services/mediaresourcemanager/ResourceManagerServiceUtils.h b/services/mediaresourcemanager/ResourceManagerServiceUtils.h
index 55ea149..32cb219 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceUtils.h
+++ b/services/mediaresourcemanager/ResourceManagerServiceUtils.h
@@ -19,6 +19,7 @@
 #define ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
 
 #include <map>
+#include <set>
 #include <memory>
 #include <vector>
 
@@ -99,10 +100,47 @@
     virtual void binderDied();
 };
 
-// A map of tuple(type, sub-type, id) and the resource parcel.
-typedef std::map<std::tuple<
-        MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>,
-        ::aidl::android::media::MediaResourceParcel> ResourceList;
+// Encapsulate Resource List as vector of resources instead of map.
+// Since the number of resource is very limited, maintaining it as
+// std::vector helps with both performance and memory requiremnts.
+struct ResourceList {
+    // Add or Update an entry into ResourceList.
+    // If a new entry is added, isNewEntry will be set to true upon return
+    // returns true on successful update, false otherwise.
+    bool add(const ::aidl::android::media::MediaResourceParcel& res, bool* isNewEntry = nullptr);
+
+    // reduce the resource usage by subtracting the resource value.
+    // If the resource value is 0 after reducing the resource usage,
+    // that entry will be removed and removedEntryValue is set to the
+    // value before it was removed upon return otherwise it will be set to -1.
+    // returns true on successful removal of the resource, false otherwise.
+    bool remove(const ::aidl::android::media::MediaResourceParcel& res,
+                long* removedEntryValue = nullptr);
+
+    // Returns true if there aren't any resource entries.
+    bool empty() const {
+        return mResourceList.empty();
+    }
+
+    // Returns resource list as a non-modifiable vectors
+    const std::vector<::aidl::android::media::MediaResourceParcel>& getResources() const {
+        return mResourceList;
+    }
+
+    // Converts resource list into string format
+    std::string toString() const;
+
+    // BEGIN: Test only function
+    // Check if two resource lists are the same.
+    bool operator==(const ResourceList& rhs) const;
+
+    // Add or Update an entry into ResourceList.
+    void addOrUpdate(const ::aidl::android::media::MediaResourceParcel& res);
+    // END: Test only function
+
+private:
+    std::vector<::aidl::android::media::MediaResourceParcel> mResourceList;
+};
 
 // Encapsulation for Resource Info, that contains
 // - pid of the app
@@ -122,15 +160,18 @@
     std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
     ResourceList resources;
     bool pendingRemoval{false};
+    uint32_t importance = 0;
 };
 
 /*
  * Resource Reclaim request info that encapsulates
  *  - the calling/requesting process pid.
+ *  - the calling/requesting client's importance.
  *  - the list of resources requesting (to be reclaimed from others)
  */
 struct ReclaimRequestInfo {
     int mCallingPid = -1;
+    uint32_t mCallingClientImportance = 0;
     const std::vector<::aidl::android::media::MediaResourceParcel>& mResources;
 };
 
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 72e249f..21e61e9 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -286,9 +286,9 @@
     {
         std::scoped_lock lock{mObserverLock};
 
-        for (auto &res : resources) {
+        for (const MediaResourceParcel& res : resources.getResources()) {
             // Skip if this resource doesn't map to any observable type.
-            MediaObservableType observableType = getObservableType(res.second);
+            MediaObservableType observableType = getObservableType(res);
             if (observableType == MediaObservableType::kInvalid) {
                 continue;
             }
@@ -303,9 +303,9 @@
                 auto calleeIt = calleeList.find(subscriber.first);
                 if (calleeIt == calleeList.end()) {
                     calleeList.emplace(subscriber.first, CalleeInfo{
-                        subscriber.second, {{observableType, res.second.value}}});
+                        subscriber.second, {{observableType, res.value}}});
                 } else {
-                    calleeIt->second.monitors.push_back({observableType, res.second.value});
+                    calleeIt->second.monitors.push_back({observableType, res.value});
                 }
             }
         }
diff --git a/services/mediaresourcemanager/ResourceTracker.cpp b/services/mediaresourcemanager/ResourceTracker.cpp
index 8dc13cc..22381c3 100644
--- a/services/mediaresourcemanager/ResourceTracker.cpp
+++ b/services/mediaresourcemanager/ResourceTracker.cpp
@@ -39,12 +39,12 @@
     bool foundResource = false;
     bool matchedPrimary =
         (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
-    for (auto it = resources.begin(); it != resources.end(); it++) {
-        if (hasResourceType(type, subType, it->second)) {
+    for (const MediaResourceParcel& res : resources.getResources()) {
+        if (hasResourceType(type, subType, res)) {
             foundResource = true;
-        } else if (it->second.subType == primarySubType) {
+        } else if (res.subType == primarySubType) {
             matchedPrimary = true;
-        } else if (isHwCodec(it->second.subType) == isHwCodec(primarySubType)) {
+        } else if (isHwCodec(res.subType) == isHwCodec(primarySubType)) {
             matchedPrimary = true;
         }
         if (matchedPrimary && foundResource) {
@@ -111,31 +111,20 @@
     ResourceList resourceAdded;
 
     for (const MediaResourceParcel& res : resources) {
-        const auto resType = std::tuple(res.type, res.subType, res.id);
-
         if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
             ALOGV("%s: Ignoring request to remove negative value of non-drm resource", __func__);
             continue;
         }
-        if (info.resources.find(resType) == info.resources.end()) {
-            if (res.value <= 0) {
-                // We can't init a new entry with negative value, although it's allowed
-                // to merge in negative values after the initial add.
-                ALOGV("%s: Ignoring request to add new resource entry with value <= 0", __func__);
-                continue;
-            }
+        bool isNewEntry = false;
+        if (!info.resources.add(res, &isNewEntry)) {
+            continue;
+        }
+        if (isNewEntry) {
             onFirstAdded(res, info.uid);
-            info.resources[resType] = res;
-        } else {
-            mergeResources(info.resources[resType], res);
         }
+
         // Add it to the list of added resources for observers.
-        auto it = resourceAdded.find(resType);
-        if (it == resourceAdded.end()) {
-            resourceAdded[resType] = res;
-        } else {
-            mergeResources(it->second, res);
-        }
+        resourceAdded.add(res);
     }
     if (info.deathNotifier == nullptr && client != nullptr) {
         info.deathNotifier = DeathNotifier::Create(client, mService, clientInfo);
@@ -147,6 +136,18 @@
     return !resourceAdded.empty();
 }
 
+bool ResourceTracker::updateResource(const aidl::android::media::ClientInfoParcel& clientInfo) {
+    ResourceInfos& infos = getResourceInfosForEdit(clientInfo.pid);
+
+    ResourceInfos::iterator found = infos.find(clientInfo.id);
+    if (found == infos.end()) {
+        return false;
+    }
+    // Update the client importance.
+    found->second.importance = std::max(0, clientInfo.importance);
+    return true;
+}
+
 bool ResourceTracker::removeResource(const ClientInfoParcel& clientInfo,
                                      const std::vector<MediaResourceParcel>& resources) {
     int32_t pid = clientInfo.pid;
@@ -174,31 +175,21 @@
     ResourceInfo& info = foundClient->second;
     ResourceList resourceRemoved;
     for (const MediaResourceParcel& res : resources) {
-        const auto resType = std::tuple(res.type, res.subType, res.id);
-
         if (res.value < 0) {
             ALOGV("%s: Ignoring request to remove negative value of resource", __func__);
             continue;
         }
-        // ignore if we don't have it
-        if (info.resources.find(resType) != info.resources.end()) {
-            MediaResourceParcel& resource = info.resources[resType];
+
+        long removedEntryValue = -1;
+        if (info.resources.remove(res, &removedEntryValue)) {
             MediaResourceParcel actualRemoved = res;
-            if (resource.value > res.value) {
-                resource.value -= res.value;
-            } else {
+            if (removedEntryValue != -1) {
                 onLastRemoved(res, info.uid);
-                actualRemoved.value = resource.value;
-                info.resources.erase(resType);
+                actualRemoved.value = removedEntryValue;
             }
 
             // Add it to the list of removed resources for observers.
-            auto it = resourceRemoved.find(resType);
-            if (it == resourceRemoved.end()) {
-                resourceRemoved[resType] = actualRemoved;
-            } else {
-                mergeResources(it->second, actualRemoved);
-            }
+            resourceRemoved.add(actualRemoved);
         }
     }
     if (mObserverService != nullptr && !resourceRemoved.empty()) {
@@ -231,8 +222,8 @@
     }
 
     const ResourceInfo& info = foundClient->second;
-    for (auto& [resType, resParcel] : info.resources) {
-        onLastRemoved(resParcel, info.uid);
+    for (const MediaResourceParcel& res : info.resources.getResources()) {
+        onLastRemoved(res, info.uid);
     }
 
     if (mObserverService != nullptr && !info.resources.empty()) {
@@ -511,8 +502,7 @@
         if (!info.pendingRemoval) {
             continue;
         }
-        for (auto it = resources.begin(); it != resources.end(); it++) {
-            const MediaResourceParcel& resource = it->second;
+        for (const MediaResourceParcel& resource : resources.getResources()) {
             if (hasResourceType(type, subType, resource)) {
                 if (resource.value > largestValue) {
                     largestValue = resource.value;
@@ -555,10 +545,73 @@
         const ResourceList& resources = info->resources;
         bool matchedPrimary =
             (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
-        for (auto it = resources.begin(); !matchedPrimary && it != resources.end(); it++) {
-            if (it->second.subType == primarySubType) {
+        for (const MediaResourceParcel& resource : resources.getResources()) {
+            if (resource.subType == primarySubType) {
                 matchedPrimary = true;
-            } else if (isHwCodec(it->second.subType) == isHwCodec(primarySubType)) {
+                break;
+            } else if (isHwCodec(resource.subType) == isHwCodec(primarySubType)) {
+                matchedPrimary = true;
+                break;
+            }
+        }
+        // Primary type doesn't match, skip the client
+        if (!matchedPrimary) {
+            continue;
+        }
+        for (const MediaResourceParcel& resource : resources.getResources()) {
+            if (hasResourceType(type, subType, resource)) {
+                if (resource.value > largestValue) {
+                    largestValue = resource.value;
+                    clientId = info->clientId;
+                    uid = info->uid;
+                }
+            }
+        }
+    }
+
+    if (clientId == -1) {
+        ALOGE("%s: can't find resource type %s and subtype %s for pid %d",
+                 __func__, asString(type), asString(subType), targetPid);
+        return false;
+    }
+
+    clientInfo.mPid = targetPid;
+    clientInfo.mUid = uid;
+    clientInfo.mClientId = clientId;
+    return true;
+}
+
+bool ResourceTracker::getLeastImportantBiggestClient(int targetPid, int32_t importance,
+                                                     MediaResource::Type type,
+                                                     MediaResource::SubType subType,
+                                                     MediaResource::SubType primarySubType,
+                                                     const std::vector<ClientInfo>& clients,
+                                                     ClientInfo& clientInfo) {
+    uid_t   uid = -1;
+    int64_t clientId = -1;
+    uint64_t largestValue = 0;
+
+    for (const ClientInfo& client : clients) {
+        // Skip the clients that doesn't belong go the targetPid
+        if (client.mPid != targetPid) {
+            continue;
+        }
+        const ResourceInfo* info = getResourceInfo(client.mPid, client.mClientId);
+        if (info == nullptr) {
+            continue;
+        }
+
+        // Make sure the importance is lower.
+        if (info->importance <= importance) {
+            continue;
+        }
+        const ResourceList& resources = info->resources;
+        bool matchedPrimary =
+            (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
+        for (const MediaResourceParcel& resource : resources.getResources()) {
+            if (resource.subType == primarySubType) {
+                matchedPrimary = true;
+            } else if (isHwCodec(resource.subType) == isHwCodec(primarySubType)) {
                 matchedPrimary = true;
             }
         }
@@ -566,8 +619,7 @@
         if (!matchedPrimary) {
             continue;
         }
-        for (auto it = resources.begin(); it != resources.end(); it++) {
-            const MediaResourceParcel& resource = it->second;
+        for (const MediaResourceParcel& resource : resources.getResources()) {
             if (hasResourceType(type, subType, resource)) {
                 if (resource.value > largestValue) {
                     largestValue = resource.value;
@@ -616,10 +668,7 @@
 
             const ResourceList& resources = info.resources;
             resourceLogs.append("        Resources:\n");
-            for (auto it = resources.begin(); it != resources.end(); it++) {
-                snprintf(buffer, SIZE, "          %s\n", toString(it->second).c_str());
-                resourceLogs.append(buffer);
-            }
+            resourceLogs.append(resources.toString());
         }
     }
     resourceLogs.append("  Process Pid override:\n");
diff --git a/services/mediaresourcemanager/ResourceTracker.h b/services/mediaresourcemanager/ResourceTracker.h
index e5f33ec..20c904d 100644
--- a/services/mediaresourcemanager/ResourceTracker.h
+++ b/services/mediaresourcemanager/ResourceTracker.h
@@ -67,6 +67,9 @@
                      const std::shared_ptr<::aidl::android::media::IResourceManagerClient>& client,
                      const std::vector<::aidl::android::media::MediaResourceParcel>& resources);
 
+    // Update the resource info, if there is any changes.
+    bool updateResource(const aidl::android::media::ClientInfoParcel& clientInfo);
+
     // Remove a set of resources from the given client.
     // returns true on success, false otherwise.
     bool removeResource(const aidl::android::media::ClientInfoParcel& clientInfo,
@@ -159,6 +162,17 @@
             ClientInfo& clientInfo,
             MediaResource::SubType primarySubType = MediaResource::SubType::kUnspecifiedSubType);
 
+    // Find the biggest client from the process pid, that has the least importance
+    // (than given importance) among the given list of clients.
+    // If applicable, match the primary type too.
+    // returns true on success, false otherwise.
+    bool getLeastImportantBiggestClient(int targetPid, int32_t importance,
+                                        MediaResource::Type type,
+                                        MediaResource::SubType subType,
+                                        MediaResource::SubType primarySubType,
+                                        const std::vector<ClientInfo>& clients,
+                                        ClientInfo& clientInfo);
+
     // Find the client that belongs to given process(pid) and with the given clientId.
     // A nullptr is returned upon failure to find the client.
     std::shared_ptr<::aidl::android::media::IResourceManagerClient> getClient(
diff --git a/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
index eb4bc42..aa14ace 100644
--- a/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
+++ b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
@@ -41,4 +41,11 @@
      * Name of the resource associated with the client.
      */
     @utf8InCpp String name;
+
+    /*
+     * Client importance, which ranges from 0 to int_max.
+     * The default importance is high (0)
+     * Based on the reclaim policy, this could be used during reclaim.
+     */
+    int importance = 0;
 }
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 58dbb8d..7e8a4a0 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -123,14 +123,16 @@
 
 
 struct TestClient : public BnResourceManagerClient {
-    TestClient(int pid, int uid, const std::shared_ptr<ResourceManagerService> &service)
-        : mPid(pid), mUid(uid), mService(service) {}
+    TestClient(int pid, int uid, int32_t clientImportance,
+               const std::shared_ptr<ResourceManagerService> &service)
+        : mPid(pid), mUid(uid), mClientImportance(clientImportance), mService(service) {}
 
     Status reclaimResource(bool* _aidl_return) override {
         ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
                                     .uid = static_cast<int32_t>(mUid),
                                     .id = getId(ref<TestClient>()),
-                                    .name = "none"};
+                                    .name = "none",
+                                    .importance = mClientImportance};
         mService->removeClient(clientInfo);
         mWasReclaimResourceCalled = true;
         *_aidl_return = true;
@@ -150,10 +152,15 @@
 
     virtual ~TestClient() {}
 
+    inline int pid() const { return mPid; }
+    inline int uid() const { return mUid; }
+    inline int32_t clientImportance() const { return mClientImportance; }
+
 private:
     bool mWasReclaimResourceCalled = false;
     int mPid;
     int mUid;
+    int32_t mClientImportance = 0;
     std::shared_ptr<ResourceManagerService> mService;
     DISALLOW_EVIL_CONSTRUCTORS(TestClient);
 };
@@ -168,6 +175,10 @@
 static const int kMidPriorityPid = 25;
 static const int kHighPriorityPid = 10;
 
+static const int32_t kHighestCodecImportance = 0;
+static const int32_t kLowestCodecImportance = 100;
+static const int32_t kMidCodecImportance = 50;
+
 using EventType = TestSystemCallback::EventType;
 using EventEntry = TestSystemCallback::EventEntry;
 bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
@@ -212,13 +223,14 @@
         } else {
             mService = ResourceManagerService::Create(new TestProcessInfo, mSystemCB);
         }
-        mTestClient1 = ::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, mService);
-        mTestClient2 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService);
-        mTestClient3 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService);
+        mTestClient1 = ::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, 0, mService);
+        mTestClient2 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
+        mTestClient3 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
     }
 
-    std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid) {
-        return ::ndk::SharedRefBase::make<TestClient>(pid, uid, mService);
+    std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid,
+                                                             int32_t importance = 0) {
+        return ::ndk::SharedRefBase::make<TestClient>(pid, uid, importance, mService);
     }
 
     sp<TestSystemCallback> mSystemCB;
@@ -233,9 +245,7 @@
         // convert resource1 to ResourceList
         ResourceList r1;
         for (size_t i = 0; i < resources1.size(); ++i) {
-            const auto &res = resources1[i];
-            const auto resType = std::tuple(res.type, res.subType, res.id);
-            r1[resType] = res;
+            r1.addOrUpdate(resources1[i]);
         }
         return r1 == resources2;
     }
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 9d4beef..b3a0932 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -209,7 +209,6 @@
 
         resources1.clear();
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
-        expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
         mService->addResource(client1Info, mTestClient1, resources1);
 
         // Expected result:
@@ -1498,6 +1497,264 @@
              client3Config.width * client3Config.height));
         EXPECT_TRUE(currentPixelCountP2 == 0);
     }
+
+    void addNonSecureVideoCodecResource(std::shared_ptr<IResourceManagerClient>& client,
+                                        std::vector<ClientInfoParcel>& infos) {
+        std::vector<MediaResourceParcel> resources;
+        resources.push_back(createNonSecureVideoCodecResource(1));
+
+        TestClient* testClient = toTestClient(client);
+        ClientInfoParcel clientInfo {.pid = static_cast<int32_t>(testClient->pid()),
+                                     .uid = static_cast<int32_t>(testClient->uid()),
+                                     .id = getId(client),
+                                     .name = "none",
+                                     .importance = testClient->clientImportance()};
+        mService->addResource(clientInfo, client, resources);
+        infos.push_back(clientInfo);
+    }
+
+    bool doReclaimResource(const ClientInfoParcel& clientInfo) {
+        bool result = false;
+        std::vector<MediaResourceParcel> reclaimResources;
+        reclaimResources.push_back(createNonSecureVideoCodecResource(1));
+        bool success = mService->reclaimResource(clientInfo, reclaimResources, &result).isOk();
+        return success && result;
+    }
+
+    // Verifies the resource reclaim policies
+    // - this verifies the reclaim policies based on:
+    //   - process priority (oom score)
+    //   - client priority
+    void testReclaimPolicies() {
+        // Create 3 clients with codec importance high, mid and low for a low
+        // priority pid.
+        std::vector<std::shared_ptr<IResourceManagerClient>> lowPriPidClients;
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kHighestCodecImportance));
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kMidCodecImportance));
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kLowestCodecImportance));
+
+        // Create 3 clients with codec importance high, mid and low for a high
+        // priority pid.
+        std::vector<std::shared_ptr<IResourceManagerClient>> highPriPidClients;
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kHighestCodecImportance));
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kMidCodecImportance));
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kLowestCodecImportance));
+
+        // Add non secure video codec resources for all the 3 clients of low priority pid.
+        std::vector<ClientInfoParcel> lowPriPidClientInfos;
+        for (auto& client : lowPriPidClients) {
+            addNonSecureVideoCodecResource(client, lowPriPidClientInfos);
+        }
+        // Add non secure video codec resources for all the 3 clients of high priority pid.
+        std::vector<ClientInfoParcel> highPriPidClientInfos;
+        for (auto& client : highPriPidClients) {
+            addNonSecureVideoCodecResource(client, highPriPidClientInfos);
+        }
+
+        // 1. Set reclaim policy as "Process Priority".
+        // - A process should be reclaiming from:
+        //    - a lower priority process if there is any
+        //    - else fail.
+        mService->setReclaimPolicy(true /*process priority*/, false /*codec importance*/);
+
+        // 1.A:
+        // - high priority process should be able to reclaim successfully.
+        // - A process should be reclaiming from the low priority process.
+        EXPECT_TRUE(doReclaimResource(highPriPidClientInfos[0]));
+        // Verify that the high priority pid's clients are untouched.
+        bool success = true;
+        for (auto& client : highPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = false;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+        // Verify that the one of the client from the low priority pid has been reclaimed.
+        success = false;
+        for (auto& client : lowPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+
+        // 1.B:
+        // - low priority process should fail to reclaim.
+        EXPECT_FALSE(doReclaimResource(lowPriPidClientInfos[0]));
+
+        // 2. Set reclaim policy as "Client Importance".
+        // - A process should be reclaiming from:
+        //    - a lower priority client from the same process if any
+        //    - else fail.
+        mService->setReclaimPolicy(false /*process priority*/, true /*codec importance*/);
+
+        // 2.A:
+        // - high priority process should be able to reclaim successfully.
+        // - Process should be reclaiming from a lower priority client from the
+        // same process.
+        EXPECT_TRUE(doReclaimResource(highPriPidClientInfos[0]));
+        // Verify that the low priority pid's clients are untouched.
+        success = true;
+        for (auto& client : lowPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = false;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+        // Verify that the one of the low priority client from the high priority
+        // pid has been reclaimed.
+        success = false;
+        for (auto& client : highPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+
+        // 2.B:
+        // - high priority process should be able to reclaim successfully.
+        // - Process should be reclaiming from a lower priority client from the
+        // same process.
+        EXPECT_TRUE(doReclaimResource(lowPriPidClientInfos[0]));
+        // Verify that the high priority pid's clients are untouched.
+        success = true;
+        for (auto& client : highPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = false;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+        // Verify that the one of the low priority client from the low priority
+        // pid has been reclaimed.
+        success = false;
+        for (auto& client : lowPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+
+        // 2.C:
+        // - lowest priority client from high priority process should fail to reclaim.
+        EXPECT_FALSE(doReclaimResource(highPriPidClientInfos[2]));
+
+        // 2.D:
+        // - lowest priority client from low priority process should fail to reclaim.
+        EXPECT_FALSE(doReclaimResource(lowPriPidClientInfos[2]));
+
+        // 3. Set reclaim policy as "Process Priority and Client Importance".
+        // - A process should be reclaiming from:
+        //    - a lower priority process if there is any
+        //    - else a lower priority client from the same process if any
+        //    - else fail.
+        mService->setReclaimPolicy(true /*process priority*/, true /*codec importance*/);
+
+        // Remove all clients from the low priority process so that we have
+        // only one process (with high priority) with all the resources.
+        for (const auto& clientInfo : lowPriPidClientInfos) {
+            mService->removeClient(clientInfo);
+        }
+        lowPriPidClientInfos.clear();
+        lowPriPidClients.clear();
+        // 3.A:
+        // - high priority process should be able to reclaim successfully.
+        EXPECT_TRUE(doReclaimResource(highPriPidClientInfos[0]));
+        // Verify that the one of the client from the high priority pid has been reclaimed.
+        success = false;
+        for (auto& client : highPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+
+        // 3.B, set the policy back to ReclaimPolicyProcessPriority
+        mService->setReclaimPolicy(true /*process priority*/, false /*codec importance*/);
+
+        // Since there is only one process, the reclaim should fail.
+        EXPECT_FALSE(doReclaimResource(highPriPidClientInfos[0]));
+
+        // 4. Set reclaim policy as "Process Priority and Client Importance".
+        // - A process should be reclaiming from:
+        //    - from a lower priority process if there are any
+        //    - else from a lower priority client from the same process if there are any
+        //    - else fail.
+        mService->setReclaimPolicy(true /*process priority*/, true /*codec importance*/);
+
+        // Remove all clients from the high priority process so that we can
+        // start a new/fresh resource allocation.
+        for (const auto& clientInfo : highPriPidClientInfos) {
+            mService->removeClient(clientInfo);
+        }
+        highPriPidClientInfos.clear();
+        highPriPidClients.clear();
+
+        // Create 3 clients with codec importance high for a low priority pid.
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kHighestCodecImportance));
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kHighestCodecImportance));
+        lowPriPidClients.push_back(
+            createTestClient(kLowPriorityPid, kTestUid1, kHighestCodecImportance));
+
+        // Create 3 clients with codec importance low for a high priority pid.
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kLowestCodecImportance));
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kLowestCodecImportance));
+        highPriPidClients.push_back(
+            createTestClient(kHighPriorityPid, kTestUid2, kLowestCodecImportance));
+
+        // Add non secure video codec resources for all the 3 clients of low priority pid.
+        for (auto& client : lowPriPidClients) {
+            addNonSecureVideoCodecResource(client, lowPriPidClientInfos);
+        }
+        // Add non secure video codec resources for all the 3 clients of high priority pid.
+        for (auto& client : highPriPidClients) {
+            addNonSecureVideoCodecResource(client, highPriPidClientInfos);
+        }
+
+        // 4.A:
+        // - high priority process should be able to reclaim successfully.
+        EXPECT_TRUE(doReclaimResource(highPriPidClientInfos[0]));
+        // Since all clients are of same priority with in high priority process,
+        // none of the clients should be reclaimed.
+        success = true;
+        for (auto& client : highPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = false;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+        // Verify that the one of the client from the low priority pid has been reclaimed.
+        success = false;
+        for (auto& client : lowPriPidClients) {
+            if (toTestClient(client)->checkIfReclaimedAndReset()) {
+                success = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(success);
+
+        // 4.B, set the policy back to ReclaimPolicyProcessPriority
+        // If low priority process tries to reclaim, it should fail as there
+        // aren't any lower priority clients or lower priority processes.
+        EXPECT_FALSE(doReclaimResource(lowPriPidClientInfos[0]));
+    }
 };
 
 class ResourceManagerServiceNewTest : public ResourceManagerServiceTest {
@@ -1678,4 +1935,8 @@
     testConcurrentCodecs();
 }
 
+TEST_F(ResourceManagerServiceNewTest, reclaimPolicies) {
+    testReclaimPolicies();
+}
+
 } // namespace android