resourcemanager: define resource model

This change:
- defines a resource model interface
- defines a base resource model that implements the current (default) resource model
- integrates the resource model with the resource manager service
This change allows extending or replacing the resource models in the future.

Bug: 294886363
Test: atest android.media.misc.cts.ResourceManagerTest
      atest android.media.misc.cts.ResourceManagerMultiTest
      /data/nativetest64/ResourceManagerService_test/ResourceManagerService_test
      /data/nativetest64/ResourceObserverService_test/ResourceObserverService_test
Change-Id: Ifbdd3de90bf9fc5e21f2e1eaa9993dcc0983810a
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index efb042c..3ede5d2 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -74,6 +74,7 @@
     name: "libresourcemanagerservice",
 
     srcs: [
+        "DefaultResourceModel.cpp",
         "ResourceManagerMetrics.cpp",
         "ResourceManagerService.cpp",
         "ResourceManagerServiceNew.cpp",
diff --git a/services/mediaresourcemanager/DefaultResourceModel.cpp b/services/mediaresourcemanager/DefaultResourceModel.cpp
new file mode 100644
index 0000000..7bad715
--- /dev/null
+++ b/services/mediaresourcemanager/DefaultResourceModel.cpp
@@ -0,0 +1,145 @@
+/*
+**
+** 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 "DefaultResourceModel"
+#include <utils/Log.h>
+
+#include "ResourceManagerServiceUtils.h"
+#include "DefaultResourceModel.h"
+#include "ResourceTracker.h"
+
+namespace android {
+
+DefaultResourceModel::DefaultResourceModel(
+        const std::shared_ptr<ResourceTracker>& resourceTracker,
+        bool supportsMultipleSecureCodecs,
+        bool supportsSecureWithNonSecureCodec)
+    : mSupportsMultipleSecureCodecs(supportsMultipleSecureCodecs),
+      mSupportsSecureWithNonSecureCodec(supportsSecureWithNonSecureCodec),
+      mResourceTracker(resourceTracker) {
+}
+
+DefaultResourceModel::~DefaultResourceModel() {
+}
+
+bool DefaultResourceModel::getAllClients(
+        const ReclaimRequestInfo& reclimRequestInfo,
+        std::vector<ClientInfo>& clients) {
+
+    clients.clear();
+    MediaResourceParcel mediaResource{.type = reclimRequestInfo.mResources[0].type,
+                                      .subType = reclimRequestInfo.mResources[0].subType};
+    ResourceRequestInfo resourceRequestInfo{reclimRequestInfo.mCallingPid, &mediaResource};
+
+    // Resolve the secure-unsecure codec conflicts if there is any.
+    switch (reclimRequestInfo.mResources[0].type) {
+    case MediaResource::Type::kSecureCodec:
+        // Looking to start a secure codec.
+        // #1. Make sure if multiple secure codecs can coexist
+        if (!mSupportsMultipleSecureCodecs) {
+            if (!mResourceTracker->getNonConflictingClients(resourceRequestInfo, clients)) {
+                // A higher priority process owns an instance of a secure codec.
+                // So this request can't be fulfilled.
+                return false;
+            }
+        }
+        // #2. Make sure a secure codec can coexist if there is an instance
+        // of non-secure codec running already.
+        if (!mSupportsSecureWithNonSecureCodec) {
+            mediaResource.type = MediaResource::Type::kNonSecureCodec;
+            if (!mResourceTracker->getNonConflictingClients(resourceRequestInfo, clients)) {
+                // A higher priority process owns an instance of a non-secure codec.
+                // So this request can't be fulfilled.
+                return false;
+            }
+        }
+        break;
+    case MediaResource::Type::kNonSecureCodec:
+        // Looking to start a non-secure codec.
+        // Make sure a non-secure codec can coexist if there is an instance
+        // of secure codec running already.
+        if (!mSupportsSecureWithNonSecureCodec) {
+            mediaResource.type = MediaResource::Type::kSecureCodec;
+            if (!mResourceTracker->getNonConflictingClients(resourceRequestInfo, clients)) {
+                // A higher priority process owns an instance of a secure codec.
+                // So this request can't be fulfilled.
+                return false;
+            }
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (!clients.empty()) {
+        // There is secure/unsecure codec co-existence conflict
+        // and we have only found processes with lower priority holding the
+        // resources. So, all of these need to be reclaimed.
+        return false;
+    }
+
+    // No more resource conflicts.
+    switch (reclimRequestInfo.mResources[0].type) {
+    case MediaResource::Type::kSecureCodec:
+    case MediaResource::Type::kNonSecureCodec:
+        // Handling Codec resource reclaim
+        return getCodecClients(reclimRequestInfo, clients);
+    case MediaResource::Type::kGraphicMemory:
+    case MediaResource::Type::kDrmSession:
+        // Handling DRM and GraphicMemory resource reclaim
+        mediaResource.id = reclimRequestInfo.mResources[0].id;
+        mediaResource.value = reclimRequestInfo.mResources[0].value;
+        return mResourceTracker->getAllClients(resourceRequestInfo, clients);
+    default:
+        break;
+    }
+
+    return !clients.empty();
+}
+
+bool DefaultResourceModel::getCodecClients(
+        const ReclaimRequestInfo& reclimRequestInfo,
+        std::vector<ClientInfo>& clients) {
+    MediaResourceParcel mediaResource;
+    ResourceRequestInfo resourceRequestInfo{reclimRequestInfo.mCallingPid, &mediaResource};
+
+    // 1. Look to find the client(s) with the other resources, for the given
+    // primary type.
+    MediaResource::SubType primarySubType = reclimRequestInfo.mResources[0].subType;
+    for (size_t index = 1; index < reclimRequestInfo.mResources.size(); index++) {
+        mediaResource.type = reclimRequestInfo.mResources[index].type;
+        mediaResource.subType = reclimRequestInfo.mResources[index].subType;
+        mResourceTracker->getAllClients(resourceRequestInfo, clients, primarySubType);
+    }
+
+    // 2. Get all clients of the same type.
+    mediaResource.type = reclimRequestInfo.mResources[0].type;
+    mediaResource.subType = reclimRequestInfo.mResources[0].subType;
+    mResourceTracker->getAllClients(resourceRequestInfo, clients);
+
+    // 3. Get all cliends of the different type.
+    MediaResourceType otherType =
+        (reclimRequestInfo.mResources[0].type == MediaResource::Type::kSecureCodec) ?
+        MediaResource::Type::kNonSecureCodec : MediaResource::Type::kSecureCodec;
+    mediaResource.type = otherType;
+    mResourceTracker->getAllClients(resourceRequestInfo, clients);
+
+    return !clients.empty();
+}
+
+} // namespace android
diff --git a/services/mediaresourcemanager/DefaultResourceModel.h b/services/mediaresourcemanager/DefaultResourceModel.h
new file mode 100644
index 0000000..1891eda
--- /dev/null
+++ b/services/mediaresourcemanager/DefaultResourceModel.h
@@ -0,0 +1,73 @@
+/*
+**
+** 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_DEFAULTRESOURCEMODEL_H_
+#define ANDROID_MEDIA_DEFAULTRESOURCEMODEL_H_
+
+#include "IResourceModel.h"
+
+namespace android {
+
+class ResourceTracker;
+
+/*
+ * Implements the Default Resource Model that handles:
+ *   - coexistence of secure codec with another secure/non-secure codecs
+ *   - sharing resources among other codecs
+ */
+class DefaultResourceModel : public IResourceModel {
+public:
+    DefaultResourceModel(const std::shared_ptr<ResourceTracker>& resourceTracker,
+                         bool supportsMultipleSecureCodecs = true,
+                         bool supportsSecureWithNonSecureCodec = true);
+    virtual ~DefaultResourceModel();
+
+    /*
+     * Set the codec co-existence properties
+     */
+    void config(bool supportsMultipleSecureCodecs, bool supportsSecureWithNonSecureCodec) {
+        mSupportsMultipleSecureCodecs = supportsMultipleSecureCodecs;
+        mSupportsSecureWithNonSecureCodec = supportsSecureWithNonSecureCodec;
+    }
+
+    /*
+     * Get a list of all clients that holds the resources requested.
+     * This implementation uses the ResourceModel to select the clients.
+     *
+     * @param[in]  reclaimRequestInfo Information about the Reclaim request
+     * @param[out] cliens The list of clients that hold the resources in question.
+     *
+     * @return true if there aren't any resource conflicts and false otherwise.
+     */
+    bool getAllClients(const ReclaimRequestInfo& reclaimRequestInfo,
+                       std::vector<ClientInfo>& clients) override;
+
+protected:
+    bool getCodecClients(const ReclaimRequestInfo& reclaimRequestInfo,
+                         std::vector<ClientInfo>& clients);
+
+protected:
+    // Keeping these protected to allow extending this implementation
+    // by other resource models.
+    bool mSupportsMultipleSecureCodecs;
+    bool mSupportsSecureWithNonSecureCodec;
+    std::shared_ptr<ResourceTracker> mResourceTracker;
+};
+
+} // namespace android
+
+#endif  // ANDROID_MEDIA_DEFAULTRESOURCEMODEL_H_
diff --git a/services/mediaresourcemanager/IResourceModel.h b/services/mediaresourcemanager/IResourceModel.h
new file mode 100644
index 0000000..f865f54
--- /dev/null
+++ b/services/mediaresourcemanager/IResourceModel.h
@@ -0,0 +1,67 @@
+/*
+**
+** 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_IRESOURCEMODEL_H_
+#define ANDROID_MEDIA_IRESOURCEMODEL_H_
+
+#include <memory>
+#include <vector>
+
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/MediaResourceParcel.h>
+
+namespace android {
+
+struct ClientInfo;
+struct ReclaimRequestInfo;
+
+/*
+ * Interface that defines Resource Model.
+ *
+ * This provides an interface that manages the resource model.
+ * The primary functionality of the implementation of this resource model is to:
+ *  1. Define a resource model for a device (or family of devices)
+ *    For example (and not limited to):
+ *      - Can a secure codec coexist with another secure or unsecured codec?
+ *      - How many codecs can coexist?
+ *      - Can one type of codecs (for example avc) coexist with another type of codec
+ *        (for example hevc) independently? OR are they sharing the common
+ *        resource pool?
+ *  2. Provide a list of clients that hold requesting resources.
+ */
+class IResourceModel {
+public:
+    IResourceModel() {}
+
+    virtual ~IResourceModel() {}
+
+    /*
+     * Get a list of all clients that holds the resources requested.
+     * This implementation uses the ResourceModel to select the clients.
+     *
+     * @param[in]  reclaimRequestInfo Information about the Reclaim request
+     * @param[out] clients The list of clients that hold the resources in question.
+     *
+     * @return true if there aren't any resource conflicts and false otherwise.
+     */
+    virtual bool getAllClients(const ReclaimRequestInfo& reclaimRequestInfo,
+                               std::vector<ClientInfo>& clients) = 0;
+};
+
+} // namespace android
+
+#endif  // ANDROID_MEDIA_IRESOURCEMODEL_H_
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 3e0ac84..4bdb6e1 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -491,6 +491,111 @@
     }
 }
 
+bool ResourceManagerService::getTargetClients(
+        int32_t callingPid,
+        const std::vector<MediaResourceParcel>& resources,
+        std::vector<ClientInfo>& targetClients) {
+    std::scoped_lock lock{mLock};
+    if (!mProcessInfo->isPidTrusted(callingPid)) {
+        pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
+        ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
+                callingPid, actualCallingPid);
+        callingPid = actualCallingPid;
+    }
+    const MediaResourceParcel *secureCodec = NULL;
+    const MediaResourceParcel *nonSecureCodec = NULL;
+    const MediaResourceParcel *graphicMemory = NULL;
+    const MediaResourceParcel *drmSession = NULL;
+    for (size_t i = 0; i < resources.size(); ++i) {
+        switch (resources[i].type) {
+            case MediaResource::Type::kSecureCodec:
+                secureCodec = &resources[i];
+                break;
+            case MediaResource::Type::kNonSecureCodec:
+                nonSecureCodec = &resources[i];
+                break;
+            case MediaResource::Type::kGraphicMemory:
+                graphicMemory = &resources[i];
+                break;
+            case MediaResource::Type::kDrmSession:
+                drmSession = &resources[i];
+                break;
+            default:
+                break;
+        }
+    }
+
+    // first pass to handle secure/non-secure codec conflict
+    if (secureCodec != NULL) {
+        MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
+                                          .subType = secureCodec->subType};
+        ResourceRequestInfo resourceRequestInfo{callingPid, &mediaResource};
+        if (!mSupportsMultipleSecureCodecs) {
+            if (!getAllClients_l(resourceRequestInfo, targetClients)) {
+                return false;
+            }
+        }
+        if (!mSupportsSecureWithNonSecureCodec) {
+            mediaResource.type = MediaResource::Type::kNonSecureCodec;
+            if (!getAllClients_l(resourceRequestInfo, targetClients)) {
+                return false;
+            }
+        }
+    }
+    if (nonSecureCodec != NULL) {
+        if (!mSupportsSecureWithNonSecureCodec) {
+            MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
+                                              .subType = nonSecureCodec->subType};
+            ResourceRequestInfo resourceRequestInfo{callingPid, &mediaResource};
+            if (!getAllClients_l(resourceRequestInfo, targetClients)) {
+                return false;
+            }
+        }
+    }
+
+    if (drmSession != NULL) {
+        ResourceRequestInfo resourceRequestInfo{callingPid, drmSession};
+        getClientForResource_l(resourceRequestInfo, targetClients);
+        if (targetClients.size() == 0) {
+            return false;
+        }
+    }
+
+    if (targetClients.size() == 0 && graphicMemory != nullptr) {
+        // if no secure/non-secure codec conflict, run second pass to handle other resources.
+        ResourceRequestInfo resourceRequestInfo{callingPid, graphicMemory};
+        getClientForResource_l(resourceRequestInfo, targetClients);
+    }
+
+    if (targetClients.size() == 0) {
+        // if we are here, run the third pass to free one codec with the same type.
+        if (secureCodec != nullptr) {
+            ResourceRequestInfo resourceRequestInfo{callingPid, secureCodec};
+            getClientForResource_l(resourceRequestInfo, targetClients);
+        }
+        if (nonSecureCodec != nullptr) {
+            ResourceRequestInfo resourceRequestInfo{callingPid, nonSecureCodec};
+            getClientForResource_l(resourceRequestInfo, targetClients);
+        }
+    }
+
+    if (targetClients.size() == 0) {
+        // if we are here, run the fourth pass to free one codec with the different type.
+        if (secureCodec != nullptr) {
+            MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
+            ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
+            getClientForResource_l(resourceRequestInfo, targetClients);
+        }
+        if (nonSecureCodec != nullptr) {
+            MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
+            ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
+            getClientForResource_l(resourceRequestInfo, targetClients);
+        }
+    }
+
+    return !targetClients.empty();
+}
+
 Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
     int32_t callingPid = clientInfo.pid;
@@ -500,105 +605,16 @@
     mServiceLog->add(log);
     *_aidl_return = false;
 
+    // Check if there are any resources to be reclaimed before processing.
+    if (resources.empty()) {
+        return Status::ok();
+    }
+
     std::vector<ClientInfo> targetClients;
-    {
-        std::scoped_lock lock{mLock};
-        if (!mProcessInfo->isPidTrusted(callingPid)) {
-            pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
-            ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
-                    callingPid, actualCallingPid);
-            callingPid = actualCallingPid;
-        }
-        const MediaResourceParcel *secureCodec = NULL;
-        const MediaResourceParcel *nonSecureCodec = NULL;
-        const MediaResourceParcel *graphicMemory = NULL;
-        const MediaResourceParcel *drmSession = NULL;
-        for (size_t i = 0; i < resources.size(); ++i) {
-            switch (resources[i].type) {
-                case MediaResource::Type::kSecureCodec:
-                    secureCodec = &resources[i];
-                    break;
-                case MediaResource::Type::kNonSecureCodec:
-                    nonSecureCodec = &resources[i];
-                    break;
-                case MediaResource::Type::kGraphicMemory:
-                    graphicMemory = &resources[i];
-                    break;
-                case MediaResource::Type::kDrmSession:
-                    drmSession = &resources[i];
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        // first pass to handle secure/non-secure codec conflict
-        if (secureCodec != NULL) {
-            MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
-                                              .subType = secureCodec->subType};
-            ResourceRequestInfo resourceRequestInfo{callingPid, &mediaResource};
-            if (!mSupportsMultipleSecureCodecs) {
-                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
-                    return Status::ok();
-                }
-            }
-            if (!mSupportsSecureWithNonSecureCodec) {
-                mediaResource.type = MediaResource::Type::kNonSecureCodec;
-                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
-                    return Status::ok();
-                }
-            }
-        }
-        if (nonSecureCodec != NULL) {
-            if (!mSupportsSecureWithNonSecureCodec) {
-                MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
-                                                  .subType = nonSecureCodec->subType};
-                ResourceRequestInfo resourceRequestInfo{callingPid, &mediaResource};
-                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
-                    return Status::ok();
-                }
-            }
-        }
-
-        if (drmSession != NULL) {
-            ResourceRequestInfo resourceRequestInfo{callingPid, drmSession};
-            getClientForResource_l(resourceRequestInfo, targetClients);
-            if (targetClients.size() == 0) {
-                return Status::ok();
-            }
-        }
-
-        if (targetClients.size() == 0 && graphicMemory != nullptr) {
-            // if no secure/non-secure codec conflict, run second pass to handle other resources.
-            ResourceRequestInfo resourceRequestInfo{callingPid, graphicMemory};
-            getClientForResource_l(resourceRequestInfo, targetClients);
-        }
-
-        if (targetClients.size() == 0) {
-            // if we are here, run the third pass to free one codec with the same type.
-            if (secureCodec != nullptr) {
-                ResourceRequestInfo resourceRequestInfo{callingPid, secureCodec};
-                getClientForResource_l(resourceRequestInfo, targetClients);
-            }
-            if (nonSecureCodec != nullptr) {
-                ResourceRequestInfo resourceRequestInfo{callingPid, nonSecureCodec};
-                getClientForResource_l(resourceRequestInfo, targetClients);
-            }
-        }
-
-        if (targetClients.size() == 0) {
-            // if we are here, run the fourth pass to free one codec with the different type.
-            if (secureCodec != nullptr) {
-                MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
-                ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
-                getClientForResource_l(resourceRequestInfo, targetClients);
-            }
-            if (nonSecureCodec != nullptr) {
-                MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
-                ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
-                getClientForResource_l(resourceRequestInfo, targetClients);
-            }
-        }
+    if (!getTargetClients(callingPid, resources, targetClients)) {
+        // Nothing to reclaim from.
+        ALOGI("%s: There aren't any clients to reclaim from", __func__);
+        return Status::ok();
     }
 
     *_aidl_return = reclaimUnconditionallyFrom(targetClients);
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index dcc0bb5..44ed005 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -137,22 +137,30 @@
     friend class DeathNotifier;
     friend class OverrideProcessInfoDeathNotifier;
 
-    // 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);
+    // Gets the client who owns biggest piece of specified resource type from pid.
+    // Returns false with no change to client if there are no clients holding resources of this
+    // type.
+    bool getBiggestClient_l(int pid, MediaResource::Type type,
+                            MediaResource::SubType subType,
+                            ClientInfo& clientsInfo,
+                            bool pendingRemovalOnly = false);
 
-    // Same method as above, but with pendingRemovalOnly as true.
+    // A helper function that gets the biggest clients of the process pid that
+    // is marked to be (pending) removed and has the needed resources.
     bool getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
                                           MediaResource::SubType subType,
                                           ClientInfo& clientsInfo);
 
-    // A helper function basically calls getLowestPriorityBiggestClient_l and adds
-    // the result client to the given Vector.
+    // From the list of clients, pick/select client(s) based on the reclaim policy.
     void getClientForResource_l(const ResourceRequestInfo& resourceRequestInfo,
                                 std::vector<ClientInfo>& clientsInfo);
+    // A helper function that pushes Reclaim Atom (for metric collection).
+    void pushReclaimAtom(const ClientInfoParcel& clientInfo,
+                         const std::vector<ClientInfo>& targetClients,
+                         bool reclaimed);
+
+    // Remove the override info for the given process
+    void removeProcessInfoOverride_l(int pid);
 
     // Eventually we want to phase out this implementation of IResourceManagerService
     // (ResourceManagerService) and replace that with the newer implementation
@@ -163,22 +171,30 @@
     // Initializes the internal state of the ResourceManagerService
     virtual void init();
 
+    // 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 std::vector<MediaResourceParcel>& resources,
+        std::vector<ClientInfo>& targetClients);
+
     // 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.
     virtual bool getAllClients_l(const ResourceRequestInfo& resourceRequestInfo,
                                  std::vector<ClientInfo>& clientsInfo);
 
-    // Gets the client who owns biggest piece of specified resource type from pid.
-    // Returns false with no change to client if there are no clients holding resources of this
-    // type.
-    virtual bool getBiggestClient_l(int pid, MediaResource::Type type,
-                                    MediaResource::SubType subType,
-                                    ClientInfo& clientsInfo,
-                                    bool pendingRemovalOnly = false);
+    // 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.
+    virtual bool getLowestPriorityBiggestClient_l(
+        const ResourceRequestInfo& resourceRequestInfo,
+        ClientInfo& clientInfo);
 
+    // override the pid of given process
     virtual bool overridePid_l(int32_t originalPid, int32_t newPid);
 
+    // override the process info of given process
     virtual bool overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient>& client,
                                        int pid, int procState, int oomScore);
 
@@ -203,14 +219,8 @@
     // Get all the resource status for dump
     virtual void getResourceDump(std::string& resourceLog) const;
 
-    void removeProcessInfoOverride_l(int pid);
-
-    // A helper function that pushes Reclaim Atom (for metric collection).
-    void pushReclaimAtom(const ClientInfoParcel& clientInfo,
-                         const std::vector<ClientInfo>& targetClients,
-                         bool reclaimed);
-
     // The following utility functions are used only for testing by ResourceManagerServiceTest
+    // START: TEST only functions
     // Get the peak concurrent pixel count (associated with the video codecs) for the process.
     long getPeakConcurrentPixelCount(int pid) const;
     // Get the current concurrent pixel count (associated with the video codecs) for the process.
@@ -223,6 +233,7 @@
     virtual const std::map<int, ResourceInfos>& getResourceMap() const {
         return mMap;
     }
+    // END: TEST only functions
 
 protected:
     mutable std::mutex mLock;
diff --git a/services/mediaresourcemanager/ResourceManagerServiceNew.cpp b/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
index 045aa3d..a819237 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
+++ b/services/mediaresourcemanager/ResourceManagerServiceNew.cpp
@@ -18,7 +18,10 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ResourceManagerServiceNew"
 #include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <mediautils/ProcessInfo.h>
 
+#include "DefaultResourceModel.h"
 #include "ResourceManagerServiceNew.h"
 #include "ResourceTracker.h"
 #include "ServiceLog.h"
@@ -36,10 +39,29 @@
     // Create the Resource Tracker
     mResourceTracker = std::make_shared<ResourceTracker>(ref<ResourceManagerServiceNew>(),
                                                          mProcessInfo);
+    setUpResourceModels();
+}
+
+void ResourceManagerServiceNew::setUpResourceModels() {
+    std::scoped_lock lock{mLock};
+    // Create/Configure the default resource model.
+    if (mDefaultResourceModel == nullptr) {
+        mDefaultResourceModel = std::make_unique<DefaultResourceModel>(
+                mResourceTracker,
+                mSupportsMultipleSecureCodecs,
+                mSupportsSecureWithNonSecureCodec);
+    } else {
+        DefaultResourceModel* resourceModel =
+            static_cast<DefaultResourceModel*>(mDefaultResourceModel.get());
+        resourceModel->config(mSupportsMultipleSecureCodecs, mSupportsSecureWithNonSecureCodec);
+    }
 }
 
 Status ResourceManagerServiceNew::config(const std::vector<MediaResourcePolicyParcel>& policies) {
-    return ResourceManagerService::config(policies);
+    Status status = ResourceManagerService::config(policies);
+    // Change in the config dictates update to the resource model.
+    setUpResourceModels();
+    return status;
 }
 
 void ResourceManagerServiceNew::setObserverService(
@@ -194,6 +216,120 @@
     return ResourceManagerService::dump(fd, args, numArgs);
 }
 
+bool ResourceManagerServiceNew::getTargetClients(
+        int callingPid,
+        const std::vector<MediaResourceParcel>& resources,
+        std::vector<ClientInfo>& targetClients) {
+    std::scoped_lock lock{mLock};
+    if (!mProcessInfo->isPidTrusted(callingPid)) {
+        pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
+        ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
+                callingPid, actualCallingPid);
+        callingPid = actualCallingPid;
+    }
+
+    // Use the Resource Model to get a list of all the clients that hold the
+    // needed/requested resources.
+    ReclaimRequestInfo reclaimRequestInfo{callingPid, resources};
+    std::vector<ClientInfo> clients;
+    if (!mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients)) {
+        if (clients.empty()) {
+            ALOGI("%s: There aren't any clients with given resources. Nothing to reclaim",
+                  __func__);
+            return false;
+        }
+        // Since there was a conflict, we need to reclaim all elements.
+        targetClients = std::move(clients);
+    } else {
+        getClientForResource_l(reclaimRequestInfo, clients, targetClients);
+    }
+    return !targetClients.empty();
+}
+
+void ResourceManagerServiceNew::getClientForResource_l(
+        const ReclaimRequestInfo& reclaimRequestInfo,
+        const std::vector<ClientInfo>& clients,
+        std::vector<ClientInfo>& targetClients) {
+    int callingPid = reclaimRequestInfo.mCallingPid;
+
+    // Before looking into other processes, check if we have clients marked for
+    // pending removal in the same process.
+    ClientInfo targetClient;
+    for (const MediaResourceParcel& resource : reclaimRequestInfo.mResources) {
+        if (mResourceTracker->getBiggestClientPendingRemoval(callingPid, resource.type,
+                                                             resource.subType, targetClient)) {
+            targetClients.emplace_back(targetClient);
+            return;
+        }
+    }
+
+    // Now find client(s) from a lowest priority process that has needed resources.
+    ResourceRequestInfo resourceRequestInfo {callingPid, nullptr};
+    for (const MediaResourceParcel& resource : reclaimRequestInfo.mResources) {
+        resourceRequestInfo.mResource = &resource;
+        if (getLowestPriorityProcessBiggestClient_l(resourceRequestInfo, clients, targetClient)) {
+            targetClients.emplace_back(targetClient);
+            return;
+        }
+    }
+}
+
+// Process priority (oom score) based reclaim:
+//   - Find a process with lowest priority (than that of calling process).
+//   - Find the bigegst client (with required resources) from that process.
+bool ResourceManagerServiceNew::getLowestPriorityProcessBiggestClient_l(
+        const ResourceRequestInfo& resourceRequestInfo,
+        const std::vector<ClientInfo>& clients,
+        ClientInfo& clientInfo) {
+    int callingPid = resourceRequestInfo.mCallingPid;
+    MediaResource::Type type = resourceRequestInfo.mResource->type;
+    MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
+    int lowestPriorityPid;
+    int lowestPriority;
+    int callingPriority;
+
+    if (!mResourceTracker->getPriority(callingPid, &callingPriority)) {
+        ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
+        return false;
+    }
+
+    // Find the lowest priority process among all the clients.
+    if (!mResourceTracker->getLowestPriorityPid(clients, lowestPriorityPid, lowestPriority)) {
+        ALOGE("%s: can't find a process with lower priority than that of the process[%d:%d]",
+              __func__, callingPid, callingPriority);
+        return false;
+    }
+
+    if (lowestPriority <= callingPriority) {
+        ALOGE("%s: lowest priority %d vs caller priority %d",
+              __func__, lowestPriority, callingPriority);
+        return false;
+    }
+
+    // Get the biggest client from this process.
+    if (!mResourceTracker->getBiggestClient(lowestPriorityPid, type, subType, clientInfo)) {
+        return false;
+    }
+
+    ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)",
+          __func__, callingPid, callingPriority, lowestPriorityPid, lowestPriority);
+    return true;
+}
+
+bool ResourceManagerServiceNew::getLowestPriorityBiggestClient_l(
+        const ResourceRequestInfo& resourceRequestInfo,
+        ClientInfo& clientInfo) {
+    //NOTE: This function is used only by the test: ResourceManagerServiceTest
+    if (resourceRequestInfo.mResource == nullptr) {
+        return false;
+    }
+    std::vector<MediaResourceParcel> resources{*resourceRequestInfo.mResource};
+    ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid, resources};
+    std::vector<ClientInfo> clients;
+    mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients);
+    return getLowestPriorityProcessBiggestClient_l(resourceRequestInfo, clients, clientInfo);
+}
+
 bool ResourceManagerServiceNew::getPriority_l(int pid, int* priority) const {
     return mResourceTracker->getPriority(pid, priority);
 }
@@ -201,22 +337,18 @@
 bool ResourceManagerServiceNew::getLowestPriorityPid_l(
         MediaResource::Type type, MediaResource::SubType subType,
         int* lowestPriorityPid, int* lowestPriority) {
+    //NOTE: This function is used only by the test: ResourceManagerServiceTest
     return mResourceTracker->getLowestPriorityPid(type, subType,
                                                   *lowestPriorityPid,
                                                   *lowestPriority);
 }
 
-bool ResourceManagerServiceNew::getBiggestClient_l(int pid, MediaResource::Type type,
-        MediaResource::SubType subType, ClientInfo& clientInfo, bool pendingRemovalOnly) {
-    return mResourceTracker->getBiggestClient(pid, type, subType,
-                                              clientInfo, pendingRemovalOnly);
-}
-
 bool ResourceManagerServiceNew::getAllClients_l(
         const ResourceRequestInfo& resourceRequestInfo,
         std::vector<ClientInfo>& clientsInfo) {
+    //NOTE: This function is used only by the test: ResourceManagerServiceTest
     MediaResource::Type type = resourceRequestInfo.mResource->type;
-    // Get list of all the clients that has requested resources.
+    // Get the list of all clients that has requested resources.
     std::vector<ClientInfo> clients;
     mResourceTracker->getAllClients(resourceRequestInfo, clients);
 
diff --git a/services/mediaresourcemanager/ResourceManagerServiceNew.h b/services/mediaresourcemanager/ResourceManagerServiceNew.h
index cd781e4..8522c4b 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceNew.h
+++ b/services/mediaresourcemanager/ResourceManagerServiceNew.h
@@ -22,6 +22,7 @@
 
 namespace android {
 
+class IResourceModel;
 class ResourceTracker;
 
 //
@@ -82,12 +83,37 @@
 
 private:
 
+    // Set up the Resource models.
+    void setUpResourceModels();
+
+    // From the list of clients, pick/select client(s) based on the reclaim policy.
+    void getClientForResource_l(
+        const ReclaimRequestInfo& reclaimRequestInfo,
+        const std::vector<ClientInfo>& clients,
+        std::vector<ClientInfo>& targetClients);
+
+    // 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 getLowestPriorityProcessBiggestClient_l(
+        const ResourceRequestInfo& resourceRequestInfo,
+        const std::vector<ClientInfo>& clients,
+        ClientInfo& clientInfo);
+
     // Initializes the internal state of the ResourceManagerService
     void init() override;
 
     void setObserverService(
             const std::shared_ptr<ResourceObserverService>& observerService) 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 getTargetClients(
+        int32_t callingPid,
+        const std::vector<MediaResourceParcel>& resources,
+        std::vector<ClientInfo>& targetClients) override;
+
     // Removes the pid from the override map.
     void removeProcessInfoOverride(int pid) override;
 
@@ -97,16 +123,18 @@
     bool getAllClients_l(const ResourceRequestInfo& resourceRequestInfo,
                          std::vector<ClientInfo>& clientsInfo) override;
 
-    // Gets the client who owns biggest piece of specified resource type from pid.
-    // Returns false with no change to client if there are no clients holding resources of this
-    // type.
-    bool getBiggestClient_l(int pid, MediaResource::Type type,
-                            MediaResource::SubType subType,
-                            ClientInfo& clientsInfo,
-                            bool pendingRemovalOnly = false) 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;
 
+    // override the process info of given process
     bool overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient>& client,
                                int pid, int procState, int oomScore) override;
 
@@ -135,6 +163,7 @@
 
 private:
     std::shared_ptr<ResourceTracker> mResourceTracker;
+    std::unique_ptr<IResourceModel> mDefaultResourceModel;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/ResourceManagerServiceUtils.h b/services/mediaresourcemanager/ResourceManagerServiceUtils.h
index 8d03143..55ea149 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceUtils.h
+++ b/services/mediaresourcemanager/ResourceManagerServiceUtils.h
@@ -18,6 +18,8 @@
 #ifndef ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
 #define ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
 
+#include <map>
+#include <memory>
 #include <vector>
 
 #include <aidl/android/media/BnResourceManagerService.h>
@@ -123,6 +125,16 @@
 };
 
 /*
+ * Resource Reclaim request info that encapsulates
+ *  - the calling/requesting process pid.
+ *  - the list of resources requesting (to be reclaimed from others)
+ */
+struct ReclaimRequestInfo {
+    int mCallingPid = -1;
+    const std::vector<::aidl::android::media::MediaResourceParcel>& mResources;
+};
+
+/*
  * Resource request info that encapsulates
  *  - the calling/requesting process pid.
  *  - the resource requesting (to be reclaimed from others)
diff --git a/services/mediaresourcemanager/ResourceTracker.cpp b/services/mediaresourcemanager/ResourceTracker.cpp
index c6255a2..2f93571 100644
--- a/services/mediaresourcemanager/ResourceTracker.cpp
+++ b/services/mediaresourcemanager/ResourceTracker.cpp
@@ -27,6 +27,45 @@
 
 namespace android {
 
+inline bool isHwCodec(MediaResource::SubType subType) {
+    return subType == MediaResource::SubType::kHwImageCodec ||
+           subType == MediaResource::SubType::kHwVideoCodec;
+}
+
+// Check whether a given resource (of type and subtype) is found in given resource list
+// that also has the given Primary SubType.
+static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
+                            const ResourceList& resources, MediaResource::SubType primarySubType) {
+    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)) {
+            foundResource = true;
+        } else if (it->second.subType == primarySubType) {
+            matchedPrimary = true;
+        } else if (isHwCodec(it->second.subType) == isHwCodec(primarySubType)) {
+            matchedPrimary = true;
+        }
+        if (matchedPrimary && foundResource) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// See if the given client is already in the list of clients.
+inline bool contains(const std::vector<ClientInfo>& clients, const int64_t& clientId) {
+    std::vector<ClientInfo>::const_iterator found =
+        std::find_if(clients.begin(), clients.end(),
+                     [clientId](const ClientInfo& client) -> bool {
+                         return client.mClientId == clientId;
+                     });
+
+    return found != clients.end();
+}
+
+
 ResourceTracker::ResourceTracker(const std::shared_ptr<ResourceManagerServiceNew>& service,
                                  const sp<ProcessInfoInterface>& processInfo) :
         mService(service),
@@ -297,8 +336,10 @@
                                                    MediaResource::SubType::kHwImageCodec,
                                                    MediaResource::SubType::kSwImageCodec}) {
                 ClientInfo clientInfo;
-                if (getBiggestClient(pid, type, subType, clientInfo, true)) {
-                    targetClients.emplace_back(clientInfo);
+                if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
+                    if (!contains(targetClients, clientInfo.mClientId)) {
+                        targetClients.emplace_back(clientInfo);
+                    }
                     continue;
                 }
             }
@@ -307,8 +348,10 @@
         default:
             ClientInfo clientInfo;
             MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
-            if (getBiggestClient(pid, type, subType, clientInfo, true)) {
-                targetClients.emplace_back(clientInfo);
+            if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
+                if (!contains(targetClients, clientInfo.mClientId)) {
+                    targetClients.emplace_back(clientInfo);
+                }
             }
             break;
         }
@@ -358,16 +401,19 @@
 }
 
 bool ResourceTracker::getAllClients(const ResourceRequestInfo& resourceRequestInfo,
-                                    std::vector<ClientInfo>& clients) {
+                                    std::vector<ClientInfo>& clients,
+                                    MediaResource::SubType primarySubType) {
     MediaResource::Type type = resourceRequestInfo.mResource->type;
     MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
     bool foundClient = false;
 
     for (auto& [pid, /* ResourceInfos */ infos] : mMap) {
         for (auto& [id, /* ResourceInfo */ info] : infos) {
-            if (hasResourceType(type, subType, info.resources)) {
-                clients.emplace_back(info.pid, info.uid, info.clientId);
-                foundClient = true;
+            if (hasResourceType(type, subType, info.resources, primarySubType)) {
+                if (!contains(clients, info.clientId)) {
+                    clients.emplace_back(info.pid, info.uid, info.clientId);
+                    foundClient = true;
+                }
             }
         }
     }
@@ -410,12 +456,38 @@
     return success;
 }
 
-bool ResourceTracker::getBiggestClient(int pid, MediaResource::Type type,
-                                       MediaResource::SubType subType,
-                                       ClientInfo& clientInfo, bool pendingRemovalOnly) {
+bool ResourceTracker::getLowestPriorityPid(const std::vector<ClientInfo>& clients,
+                                           int& lowestPriorityPid, int& lowestPriority) {
+    int pid = -1;
+    int priority = -1;
+    for (const ClientInfo& client : clients) {
+        int tempPriority = -1;
+        if (!getPriority(client.mPid, &tempPriority)) {
+            ALOGV("%s: can't get priority of pid %d, skipped", __func__, client.mPid);
+            // TODO: remove this pid from mMap?
+            continue;
+        }
+        if (pid == -1 || tempPriority > priority) {
+            // initial the value
+            pid = client.mPid;
+            priority = tempPriority;
+        }
+    }
+
+    bool success = (pid != -1);
+
+    if (success) {
+        lowestPriorityPid = pid;
+        lowestPriority = priority;
+    }
+    return success;
+}
+
+bool ResourceTracker::getBiggestClientPendingRemoval(int pid, MediaResource::Type type,
+                                                     MediaResource::SubType subType,
+                                                     ClientInfo& clientInfo) {
     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
     if (found == mMap.end()) {
-        ALOGE_IF(!pendingRemovalOnly, "%s: can't find resource info for pid %d", __func__, pid);
         return false;
     }
 
@@ -425,10 +497,48 @@
     const ResourceInfos& infos = found->second;
     for (const auto& [id, /* ResourceInfo */ info] : infos) {
         const ResourceList& resources = info.resources;
-        if (pendingRemovalOnly && !info.pendingRemoval) {
+        // Skip if the client is not marked pending removal.
+        if (!info.pendingRemoval) {
             continue;
         }
         for (auto it = resources.begin(); it != resources.end(); it++) {
+            const MediaResourceParcel& resource = it->second;
+            if (hasResourceType(type, subType, resource)) {
+                if (resource.value > largestValue) {
+                    largestValue = resource.value;
+                    clientId = info.clientId;
+                    uid = info.uid;
+                }
+            }
+        }
+    }
+
+    if (clientId == -1) {
+        return false;
+    }
+
+    clientInfo.mPid = pid;
+    clientInfo.mUid = uid;
+    clientInfo.mClientId = clientId;
+    return true;
+}
+
+bool ResourceTracker::getBiggestClient(int pid, MediaResource::Type type,
+                                       MediaResource::SubType subType,
+                                       ClientInfo& clientInfo) {
+    std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
+    if (found == mMap.end()) {
+        ALOGE("%s: can't find resource info for pid %d", __func__, pid);
+        return false;
+    }
+
+    uid_t   uid = -1;
+    int64_t clientId = -1;
+    uint64_t largestValue = 0;
+    const ResourceInfos& infos = found->second;
+    for (const auto& [id, info] : infos) {
+        const ResourceList& resources = info.resources;
+        for (auto it = resources.begin(); it != resources.end(); it++) {
             const MediaResourceParcel &resource = it->second;
             if (hasResourceType(type, subType, resource)) {
                 if (resource.value > largestValue) {
@@ -441,9 +551,8 @@
     }
 
     if (clientId == -1) {
-        ALOGE_IF(!pendingRemovalOnly,
-                 "%s: can't find resource type %s and subtype %s for pid %d",
-                 __func__, asString(type), asString(subType), pid);
+        ALOGE("%s: can't find resource type %s and subtype %s for pid %d",
+              __func__, asString(type), asString(subType), pid);
         return false;
     }
 
diff --git a/services/mediaresourcemanager/ResourceTracker.h b/services/mediaresourcemanager/ResourceTracker.h
index 06fb914..eb89d12 100644
--- a/services/mediaresourcemanager/ResourceTracker.h
+++ b/services/mediaresourcemanager/ResourceTracker.h
@@ -109,12 +109,15 @@
     void removeProcessInfoOverride(int pid);
 
     // Find all clients that have given resources.
+    // If applicable, match the primary type too.
     // The |clients| (list) isn't cleared by this function to allow calling this
     // function multiple times for different resources.
     // returns true upon finding at lease one client with the given resource request info,
     // false otherwise (no clients)
-    bool getAllClients(const ResourceRequestInfo& resourceRequestInfo,
-                       std::vector<ClientInfo>& clients);
+    bool getAllClients(
+        const ResourceRequestInfo& resourceRequestInfo,
+        std::vector<ClientInfo>& clients,
+        MediaResource::SubType primarySubType = MediaResource::SubType::kUnspecifiedSubType);
 
     // Look for the lowest priority process with the given resources.
     // Upon success lowestPriorityPid and lowestPriority are
@@ -124,6 +127,18 @@
     bool getLowestPriorityPid(MediaResource::Type type, MediaResource::SubType subType,
                               int& lowestPriorityPid, int& lowestPriority);
 
+    // Look for the lowest priority process with the given client list.
+    // returns true on success, false otherwise.
+    bool getLowestPriorityPid(const std::vector<ClientInfo>& clients,
+                              int& lowestPriorityPid, int& lowestPriority);
+
+    // Find the biggest client of the given process with given resources,
+    // that is marked as pending to be removed.
+    // returns true on success, false otherwise.
+    bool getBiggestClientPendingRemoval(
+        int pid, MediaResource::Type type, MediaResource::SubType subType,
+        ClientInfo& clientInfo);
+
     // Find the biggest client of the given process with given resources.
     // If pendingRemovalOnly is set, then it will look for only those clients
     // that are marked for removing.
@@ -131,7 +146,7 @@
     // Upon failure to find a client, it will return false without updating
     // clientInfo.
     bool getBiggestClient(int pid, MediaResource::Type type, MediaResource::SubType subType,
-                          ClientInfo& clientInfo, bool pendingRemovalOnly = false);
+                          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.
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 58ddf1a..9d4beef 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -79,6 +79,18 @@
 public:
     ResourceManagerServiceTest(bool newRM = false) : ResourceManagerServiceTestBase(newRM) {}
 
+    void updateConfig(bool bSupportsMultipleSecureCodecs, bool bSupportsSecureWithNonSecureCodec) {
+        std::vector<MediaResourcePolicyParcel> policies;
+        policies.push_back(
+                MediaResourcePolicy(
+                        IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
+                        bSupportsMultipleSecureCodecs ? "true" : "false"));
+        policies.push_back(
+                MediaResourcePolicy(
+                        IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
+                        bSupportsSecureWithNonSecureCodec ? "true" : "false"));
+        mService->config(policies);
+    }
 
     // test set up
     // ---------------------------------------------------------------------------------
@@ -213,29 +225,11 @@
         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
 
-        std::vector<MediaResourcePolicyParcel> policies1;
-        policies1.push_back(
-                MediaResourcePolicy(
-                        IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
-                        "true"));
-        policies1.push_back(
-                MediaResourcePolicy(
-                        IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
-                        "false"));
-        mService->config(policies1);
+        updateConfig(true, false);
         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
 
-        std::vector<MediaResourcePolicyParcel> policies2;
-        policies2.push_back(
-                MediaResourcePolicy(
-                        IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
-                        "false"));
-        policies2.push_back(
-                MediaResourcePolicy(
-                        IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
-                        "true"));
-        mService->config(policies2);
+        updateConfig(false, true);
         EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
     }
@@ -339,8 +333,7 @@
         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = false;
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(false, true);
 
             // priority too low to reclaim resource
             ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
@@ -374,7 +367,7 @@
                                      .name = "none"};
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
@@ -402,7 +395,7 @@
 
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
@@ -428,7 +421,7 @@
 
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             mService->markClientForPendingRemoval(client2Info);
 
@@ -520,8 +513,7 @@
         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = false;
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(false, true);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -546,8 +538,7 @@
         // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = false;
-            mService->mSupportsSecureWithNonSecureCodec = false;
+            updateConfig(false, false);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -567,8 +558,7 @@
         // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = true;
-            mService->mSupportsSecureWithNonSecureCodec = false;
+            updateConfig(true, false);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -599,8 +589,7 @@
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = true;
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -630,8 +619,7 @@
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsMultipleSecureCodecs = true;
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -677,7 +665,7 @@
         // ### secure codec can't coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = false;
+            updateConfig(true, false);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -703,7 +691,7 @@
         // ### secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             // priority too low
             CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
@@ -733,7 +721,7 @@
         // ### secure codec can coexist with non-secure codec ###
         {
             addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
+            updateConfig(true, true);
 
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));