Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56fda31d authored by Girish's avatar Girish
Browse files

resourcemanager: abstract arguments into a structure

As part of refactoring the resource manager, reduce the
number of arguments passed to the functions by moving all
the related arguments into a structrue.
Also
- replace a typedef with the actual type for better readability.
- group related functions together
- add/fix documents for the functions
Since, there is no change in the functionality or addition
or modifications of ResourceManagerService binder APIs,
this change is unflagged.

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: I862dd33c90ce3c6a075a1fcd5bbc355a4eb6e709
parent 277c4a44
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -427,8 +427,8 @@ void ResourceManagerMetrics::pushConcurrentUsageReport(int32_t pid, uid_t uid) {

void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
                                             const std::vector<int>& priorities,
                        const std::vector<std::shared_ptr<IResourceManagerClient>>& clients,
                        const PidUidVector& idList, bool reclaimed) {
                                             const std::vector<ClientInfo>& targetClients,
                                             bool reclaimed) {
    // Construct the metrics for codec reclaim as a pushed atom.
    // 1. Information about the requester.
    //  - UID and the priority (oom score)
@@ -453,7 +453,7 @@ void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
    //    - UID and the Priority (oom score)
    int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
    if (!reclaimed) {
      if (clients.size() == 0) {
      if (targetClients.size() == 0) {
        // No clients to reclaim from
        reclaimStatus =
            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
@@ -463,10 +463,9 @@ void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
      }
    }
    int32_t noOfCodecsReclaimed = clients.size();
    int32_t noOfCodecsReclaimed = targetClients.size();
    int32_t targetIndex = 1;
    for (PidUidVector::const_reference id : idList) {
        int32_t targetUid = id.second;
    for (const ClientInfo& targetClient : targetClients) {
        int targetPriority = priorities[targetIndex];
        // Post the pushed atom
        int result = stats_write(
@@ -478,7 +477,7 @@ void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
            reclaimStatus,
            noOfCodecsReclaimed,
            targetIndex,
            targetUid,
            targetClient.mUid,
            targetPriority);
        ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
              "Requester[pid(%d): uid(%d): priority(%d)] "
@@ -490,7 +489,7 @@ void ResourceManagerMetrics::pushReclaimAtom(const ClientInfoParcel& clientInfo,
              __func__, callingPid, requesterUid, requesterPriority,
              clientName.c_str(), noOfConcurrentCodecs,
              reclaimStatus, noOfCodecsReclaimed,
              targetIndex, id.first, targetUid, targetPriority, result);
              targetIndex, targetClient.mPid, targetClient.mUid, targetPriority, result);
        targetIndex++;
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -135,8 +135,8 @@ public:
    // To be called when after a reclaim event.
    void pushReclaimAtom(const ClientInfoParcel& clientInfo,
                         const std::vector<int>& priorities,
                         const std::vector<std::shared_ptr<IResourceManagerClient>>& clients,
                         const PidUidVector& idList, bool reclaimed);
                         const std::vector<ClientInfo>& targetClients,
                         bool reclaimed);

    // Add this pid/uid set to monitor for the process termination state.
    void addPid(int pid, uid_t uid = 0);
+90 −72
Original line number Diff line number Diff line
@@ -585,16 +585,16 @@ Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo
    return Status::ok();
}

void ResourceManagerService::getClientForResource_l(int callingPid,
        const MediaResourceParcel *res,
        PidUidVector* idVector,
        std::vector<std::shared_ptr<IResourceManagerClient>>* clients) {
void ResourceManagerService::getClientForResource_l(
        const ResourceRequestInfo& resourceRequestInfo,
        std::vector<ClientInfo>& clientsInfo) {
    const MediaResourceParcel* res = resourceRequestInfo.mResource;
    if (res == NULL) {
        return;
    }
    std::shared_ptr<IResourceManagerClient> client;
    if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, idVector, &client)) {
        clients->push_back(client);
    ClientInfo clientInfo;
    if (getLowestPriorityBiggestClient_l(resourceRequestInfo, clientInfo)) {
        clientsInfo.push_back(clientInfo);
    }
}

@@ -607,8 +607,7 @@ Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInf
    mServiceLog->add(log);
    *_aidl_return = false;

    std::vector<std::shared_ptr<IResourceManagerClient>> clients;
    PidUidVector idVector;
    std::vector<ClientInfo> targetClients;
    {
        std::scoped_lock lock{mLock};
        if (!mProcessInfo->isPidTrusted(callingPid)) {
@@ -642,98 +641,116 @@ Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInf

        // 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(callingPid, MediaResource::Type::kSecureCodec,
                            secureCodec->subType, &idVector, &clients)) {
                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
                    return Status::ok();
                }
            }
            if (!mSupportsSecureWithNonSecureCodec) {
                if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec,
                            secureCodec->subType, &idVector, &clients)) {
                mediaResource.type = MediaResource::Type::kNonSecureCodec;
                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
                    return Status::ok();
                }
            }
        }
        if (nonSecureCodec != NULL) {
            if (!mSupportsSecureWithNonSecureCodec) {
                if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
                        nonSecureCodec->subType, &idVector, &clients)) {
                MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
                                                  .subType = nonSecureCodec->subType};
                ResourceRequestInfo resourceRequestInfo{callingPid, &mediaResource};
                if (!getAllClients_l(resourceRequestInfo, targetClients)) {
                    return Status::ok();
                }
            }
        }

        if (drmSession != NULL) {
            getClientForResource_l(callingPid, drmSession, &idVector, &clients);
            if (clients.size() == 0) {
            ResourceRequestInfo resourceRequestInfo{callingPid, drmSession};
            getClientForResource_l(resourceRequestInfo, targetClients);
            if (targetClients.size() == 0) {
                return Status::ok();
            }
        }

        if (clients.size() == 0) {
        if (targetClients.size() == 0 && graphicMemory != nullptr) {
            // if no secure/non-secure codec conflict, run second pass to handle other resources.
            getClientForResource_l(callingPid, graphicMemory, &idVector, &clients);
            ResourceRequestInfo resourceRequestInfo{callingPid, graphicMemory};
            getClientForResource_l(resourceRequestInfo, targetClients);
        }

        if (clients.size() == 0) {
        if (targetClients.size() == 0) {
            // if we are here, run the third pass to free one codec with the same type.
            getClientForResource_l(callingPid, secureCodec, &idVector, &clients);
            getClientForResource_l(callingPid, nonSecureCodec, &idVector, &clients);
            if (secureCodec != nullptr) {
                ResourceRequestInfo resourceRequestInfo{callingPid, secureCodec};
                getClientForResource_l(resourceRequestInfo, targetClients);
            }
            if (nonSecureCodec != nullptr) {
                ResourceRequestInfo resourceRequestInfo{callingPid, nonSecureCodec};
                getClientForResource_l(resourceRequestInfo, targetClients);
            }
        }

        if (clients.size() == 0) {
        if (targetClients.size() == 0) {
            // if we are here, run the fourth pass to free one codec with the different type.
            if (secureCodec != NULL) {
            if (secureCodec != nullptr) {
                MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
                getClientForResource_l(callingPid, &temp, &idVector, &clients);
                ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
                getClientForResource_l(resourceRequestInfo, targetClients);
            }
            if (nonSecureCodec != NULL) {
            if (nonSecureCodec != nullptr) {
                MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
                getClientForResource_l(callingPid, &temp, &idVector, &clients);
                ResourceRequestInfo resourceRequestInfo{callingPid, &temp};
                getClientForResource_l(resourceRequestInfo, targetClients);
            }
        }
    }

    *_aidl_return = reclaimUnconditionallyFrom(clients);
    *_aidl_return = reclaimUnconditionallyFrom(targetClients);

    // Log Reclaim Pushed Atom to statsd
    pushReclaimAtom(clientInfo, clients, idVector, *_aidl_return);
    pushReclaimAtom(clientInfo, targetClients, *_aidl_return);

    return Status::ok();
}

void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
                        const std::vector<std::shared_ptr<IResourceManagerClient>>& clients,
                        const PidUidVector& idVector, bool reclaimed) {
                                             const std::vector<ClientInfo>& targetClients,
                                             bool reclaimed) {
    int32_t callingPid = clientInfo.pid;
    int requesterPriority = -1;
    getPriority_l(callingPid, &requesterPriority);
    std::vector<int> priorities;
    priorities.push_back(requesterPriority);

    for (PidUidVector::const_reference id : idVector) {
    for (const ClientInfo& targetClient : targetClients) {
        int targetPriority = -1;
        getPriority_l(id.first, &targetPriority);
        getPriority_l(targetClient.mPid, &targetPriority);
        priorities.push_back(targetPriority);
    }
    mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, clients,
                                             idVector, reclaimed);
    mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, targetClients, reclaimed);
}

bool ResourceManagerService::reclaimUnconditionallyFrom(
        const std::vector<std::shared_ptr<IResourceManagerClient>>& clients) {
    if (clients.size() == 0) {
        const std::vector<ClientInfo>& targetClients) {
    if (targetClients.size() == 0) {
        return false;
    }

    std::shared_ptr<IResourceManagerClient> failedClient;
    for (size_t i = 0; i < clients.size(); ++i) {
        String8 log = String8::format("reclaimResource from client %p", clients[i].get());
    for (const ClientInfo& targetClient : targetClients) {
        if (targetClient.mClient == nullptr) {
            // skip already released clients.
            continue;
        }
        String8 log = String8::format("reclaimResource from client %p", targetClient.mClient.get());
        mServiceLog->add(log);
        bool success;
        Status status = clients[i]->reclaimResource(&success);
        Status status = targetClient.mClient->reclaimResource(&success);
        if (!status.isOk() || !success) {
            failedClient = clients[i];
            failedClient = targetClient.mClient;
            break;
        }
    }
@@ -891,7 +908,7 @@ Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t
    String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
    mServiceLog->add(log);

    std::vector<std::shared_ptr<IResourceManagerClient>> clients;
    std::vector<ClientInfo> targetClients;
    {
        std::scoped_lock lock{mLock};
        if (!mProcessInfo->isPidTrusted(pid)) {
@@ -918,7 +935,7 @@ Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t
                        std::shared_ptr<IResourceManagerClient> client;
                        uid_t uid = 0;
                        if (getBiggestClientPendingRemoval_l(pid, type, subType, uid, &client)) {
                            clients.push_back(client);
                            targetClients.emplace_back(pid, uid, client);
                            continue;
                        }
                    }
@@ -929,15 +946,15 @@ Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t
                    uid_t uid = 0;
                    if (getBiggestClientPendingRemoval_l(pid, type,
                            MediaResource::SubType::kUnspecifiedSubType, uid, &client)) {
                        clients.push_back(client);
                        targetClients.emplace_back(pid, uid, client);
                    }
                    break;
            }
        }
    }

    if (!clients.empty()) {
        reclaimUnconditionallyFrom(clients);
    if (!targetClients.empty()) {
        reclaimUnconditionallyFrom(targetClients);
    }
    return Status::ok();
}
@@ -954,52 +971,51 @@ bool ResourceManagerService::getPriority_l(int pid, int* priority) {
    return mProcessInfo->getPriority(newPid, priority);
}

bool ResourceManagerService::getAllClients_l(int callingPid, MediaResource::Type type,
        MediaResource::SubType subType,
        PidUidVector* idVector,
        std::vector<std::shared_ptr<IResourceManagerClient>>* clients) {
    std::vector<std::shared_ptr<IResourceManagerClient>> temp;
    PidUidVector tempIdList;
bool ResourceManagerService::getAllClients_l(
        const ResourceRequestInfo& resourceRequestInfo,
        std::vector<ClientInfo>& clientsInfo) {
    MediaResource::Type type = resourceRequestInfo.mResource->type;
    MediaResource::SubType subType = resourceRequestInfo.mResource->subType;

    for (auto& [pid, infos] : mMap) {
        for (const auto& [id, info] : infos) {
            if (hasResourceType(type, subType, info.resources)) {
                if (!isCallingPriorityHigher_l(callingPid, pid)) {
                if (!isCallingPriorityHigher_l(resourceRequestInfo.mCallingPid, pid)) {
                    // some higher/equal priority process owns the resource,
                    // this request can't be fulfilled.
                    ALOGE("getAllClients_l: can't reclaim resource %s from pid %d",
                            asString(type), pid);
                    ALOGE("%s: can't reclaim resource %s from pid %d",
                          __func__, asString(type), pid);
                    clientsInfo.clear();
                    return false;
                }
                temp.push_back(info.client);
                tempIdList.emplace_back(pid, info.uid);
                clientsInfo.emplace_back(pid, info.uid, info.client);
            }
        }
    }
    if (temp.size() == 0) {
        ALOGV("getAllClients_l: didn't find any resource %s", asString(type));
        return true;
    if (clientsInfo.size() == 0) {
        ALOGV("%s: didn't find any resource %s", __func__, asString(type));
    }

    clients->insert(std::end(*clients), std::begin(temp), std::end(temp));
    idVector->insert(std::end(*idVector), std::begin(tempIdList), std::end(tempIdList));
    return true;
}

bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
        MediaResource::Type type,
        MediaResource::SubType subType,
        PidUidVector* idVector,
        std::shared_ptr<IResourceManagerClient> *client) {
bool ResourceManagerService::getLowestPriorityBiggestClient_l(
        const ResourceRequestInfo& resourceRequestInfo,
        ClientInfo& clientsInfo) {
    int callingPid = resourceRequestInfo.mCallingPid;
    MediaResource::Type type = resourceRequestInfo.mResource->type;
    MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
    int lowestPriorityPid;
    int lowestPriority;
    int callingPriority;
    uid_t uid = 0;
    std::shared_ptr<IResourceManagerClient> client;

    // Before looking into other processes, check if we have clients marked for
    // pending removal in the same process.
    if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, client)) {
        idVector->emplace_back(callingPid, uid);
    if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, &client)) {
        clientsInfo.mPid = callingPid;
        clientsInfo.mUid = uid;
        clientsInfo.mClient = client;
        return true;
    }
    if (!getPriority_l(callingPid, &callingPriority)) {
@@ -1016,11 +1032,13 @@ bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
        return false;
    }

    if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, client)) {
    if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, &client)) {
        return false;
    }

    idVector->emplace_back(lowestPriorityPid, uid);
    clientsInfo.mPid = lowestPriorityPid;
    clientsInfo.mUid = uid;
    clientsInfo.mClient = client;
    return true;
}

+56 −26
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@
namespace android {

class DeathNotifier;
class ResourceManagerService;
class ResourceObserverService;
class ServiceLog;
struct ProcessInfoInterface;
@@ -61,8 +60,39 @@ struct ResourceInfo {
    bool pendingRemoval{false};
};

// vector of <PID, UID>
typedef std::vector<std::pair<int32_t, uid_t>> PidUidVector;
/*
 * Resource request info that encapsulates
 *  - the calling/requesting process pid.
 *  - the resource requesting (to be reclaimed from others)
 */
struct ResourceRequestInfo {
    // uid of the calling/requesting process.
    int mCallingPid = -1;
    // resources requested.
    const ::aidl::android::media::MediaResourceParcel* mResource;
};

/*
 * Structure that defines the Client - a possible target to relcaim from.
 * This encapsulates pid, uid of the process and the client.
 * based on the reclaim policy.
 */
struct ClientInfo {
    // pid of the process.
    pid_t mPid;
    // uid of the process.
    uid_t mUid;
    // Client to relcaim from.
    std::shared_ptr<::aidl::android::media::IResourceManagerClient> mClient;
    ClientInfo(
        pid_t pid = -1,
        uid_t uid = -1,
        const std::shared_ptr<::aidl::android::media::IResourceManagerClient>& client = nullptr)
        : mPid(pid),
          mUid(uid),
          mClient(client) {
    }
};

typedef std::map<int64_t, ResourceInfo> ResourceInfos;
typedef std::map<int, ResourceInfos> PidResourceInfosMap;
@@ -134,29 +164,23 @@ private:
    // Reclaims resources from |clients|. Returns true if reclaim succeeded
    // for all clients.
    bool reclaimUnconditionallyFrom(
        const std::vector<std::shared_ptr<IResourceManagerClient>>& clients);
        const 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.
    bool getAllClients_l(int callingPid, MediaResource::Type type, MediaResource::SubType subType,
            PidUidVector* idList,
            std::vector<std::shared_ptr<IResourceManagerClient>>* clients);
    bool getAllClients_l(const ResourceRequestInfo& resourceRequestInfo,
                         std::vector<ClientInfo>& clientsInfo);

    // 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(int callingPid, MediaResource::Type type,
            MediaResource::SubType subType, PidUidVector* idList,
            std::shared_ptr<IResourceManagerClient> *client);

    // 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 *pid,
                int *priority);
    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 holdiing resources of thisi
    // 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,
                            uid_t& uid, std::shared_ptr<IResourceManagerClient> *client,
@@ -166,13 +190,14 @@ private:
                                          MediaResource::SubType subType, uid_t& uid,
                                          std::shared_ptr<IResourceManagerClient>* client);

    // A helper function that returns true if the callingPid has higher priority than pid.
    // Returns false otherwise.
    bool isCallingPriorityHigher_l(int callingPid, int pid);

    // A helper function basically calls getLowestPriorityBiggestClient_l and add
    // A helper function basically calls getLowestPriorityBiggestClient_l and adds
    // the result client to the given Vector.
    void getClientForResource_l(int callingPid, const MediaResourceParcel *res,
            PidUidVector* idList,
            std::vector<std::shared_ptr<IResourceManagerClient>>* clients);
    void getClientForResource_l(const ResourceRequestInfo& resourceRequestInfo,
                                std::vector<ClientInfo>& clientsInfo);

    void onFirstAdded(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
    void onLastRemoved(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
@@ -188,9 +213,14 @@ private:
    void removeProcessInfoOverride_l(int pid);

    void pushReclaimAtom(const ClientInfoParcel& clientInfo,
                         const std::vector<std::shared_ptr<IResourceManagerClient>>& clients,
                         const PidUidVector& idList, bool reclaimed);
                         const std::vector<ClientInfo>& targetClients,
                         bool reclaimed);

    // The following utility functions are used only for testing by ResourceManagerServiceTest
    // 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);
    // 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.
+24 −21

File changed.

Preview size limit exceeded, changes collapsed.