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

Commit 6a6044d8 authored by Girish's avatar Girish
Browse files

resourcemanager: refactor resource map into an abstraction

This CL moves the resource tracking into a new abstraction
ResourceTracker by moving all the related codec from the
ResourceManagerServiceNew into this new class.

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
      /data/nativetest64/ServiceLog_test/ServiceLog_test
Change-Id: I0ac5739cbefff3756cc3a9f20a6bc6c0ddd9e732
parent 1484e5dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ cc_library {
        "ResourceManagerServiceNew.cpp",
        "ResourceObserverService.cpp",
        "ResourceManagerServiceUtils.cpp",
        "ResourceTracker.cpp",
        "ServiceLog.cpp",
        "UidObserver.cpp",

+111 −82
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@
#include <mediautils/SchedulingPolicyService.h>
#include <com_android_media_codec_flags.h>

#include "IMediaResourceMonitor.h"
#include "ResourceManagerMetrics.h"
#include "ResourceManagerServiceNew.h"
#include "ResourceObserverService.h"
@@ -41,29 +40,52 @@ namespace CodecFeatureFlags = com::android::media::codec::flags;

namespace android {

static void notifyResourceGranted(int pid, const std::vector<MediaResourceParcel>& resources) {
    static const char* const kServiceName = "media_resource_monitor";
    sp<IBinder> binder = defaultServiceManager()->checkService(String16(kServiceName));
    if (binder != NULL) {
        sp<IMediaResourceMonitor> service = interface_cast<IMediaResourceMonitor>(binder);
        for (size_t i = 0; i < resources.size(); ++i) {
            switch (resources[i].subType) {
                case MediaResource::SubType::kHwAudioCodec:
                case MediaResource::SubType::kSwAudioCodec:
                    service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_AUDIO_CODEC);
                    break;
                case MediaResource::SubType::kHwVideoCodec:
                case MediaResource::SubType::kSwVideoCodec:
                    service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_VIDEO_CODEC);
                    break;
                case MediaResource::SubType::kHwImageCodec:
                case MediaResource::SubType::kSwImageCodec:
                    service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_IMAGE_CODEC);
                    break;
                case MediaResource::SubType::kUnspecifiedSubType:
                    break;
void ResourceManagerService::getResourceDump(std::string& resourceLog) const {
    PidResourceInfosMap mapCopy;
    std::map<int, int> overridePidMapCopy;
    {
        std::scoped_lock lock{mLock};
        mapCopy = mMap;  // Shadow copy, real copy will happen on write.
        overridePidMapCopy = mOverridePidMap;
    }

    const size_t SIZE = 256;
    char buffer[SIZE];
    resourceLog.append("  Processes:\n");
    for (const auto& [pid, infos] : mapCopy) {
        snprintf(buffer, SIZE, "    Pid: %d\n", pid);
        resourceLog.append(buffer);
        int priority = 0;
        if (getPriority_l(pid, &priority)) {
            snprintf(buffer, SIZE, "    Priority: %d\n", priority);
        } else {
            snprintf(buffer, SIZE, "    Priority: <unknown>\n");
        }
        resourceLog.append(buffer);

        for (const auto& [infoKey, info] : infos) {
            resourceLog.append("      Client:\n");
            snprintf(buffer, SIZE, "        Id: %lld\n", (long long)info.clientId);
            resourceLog.append(buffer);

            std::string clientName = info.name;
            snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
            resourceLog.append(buffer);

            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("  Process Pid override:\n");
    for (auto it = overridePidMapCopy.begin(); it != overridePidMapCopy.end(); ++it) {
        snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n",
            it->first, it->second);
        resourceLog.append(buffer);
    }
}

@@ -79,20 +101,20 @@ binder_status_t ResourceManagerService::dump(int fd, const char** /*args*/, uint
        return PERMISSION_DENIED;
    }

    PidResourceInfosMap mapCopy;
    bool supportsMultipleSecureCodecs;
    bool supportsSecureWithNonSecureCodec;
    std::map<int, int> overridePidMapCopy;
    String8 serviceLog;
    {
        std::scoped_lock lock{mLock};
        mapCopy = mMap;  // Shadow copy, real copy will happen on write.
        supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs;
        supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec;
        serviceLog = mServiceLog->toString("    " /* linePrefix */);
        overridePidMapCopy = mOverridePidMap;
    }

    // Get all the resource (and overload pid) logs
    std::string resourceLog;
    getResourceDump(resourceLog);

    const size_t SIZE = 256;
    char buffer[SIZE];
    snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
@@ -104,41 +126,8 @@ binder_status_t ResourceManagerService::dump(int fd, const char** /*args*/, uint
            supportsSecureWithNonSecureCodec);
    result.append(buffer);

    result.append("  Processes:\n");
    for (const auto& [pid, infos] : mapCopy) {
        snprintf(buffer, SIZE, "    Pid: %d\n", pid);
        result.append(buffer);
        int priority = 0;
        if (getPriority_l(pid, &priority)) {
            snprintf(buffer, SIZE, "    Priority: %d\n", priority);
        } else {
            snprintf(buffer, SIZE, "    Priority: <unknown>\n");
        }
        result.append(buffer);

        for (const auto& [infoKey, info] : infos) {
            result.append("      Client:\n");
            snprintf(buffer, SIZE, "        Id: %lld\n", (long long)info.clientId);
            result.append(buffer);

            std::string clientName = info.name;
            snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
            result.append(buffer);
    result.append(resourceLog.c_str());

            const ResourceList& resources = info.resources;
            result.append("        Resources:\n");
            for (auto it = resources.begin(); it != resources.end(); it++) {
                snprintf(buffer, SIZE, "          %s\n", toString(it->second).c_str());
                result.append(buffer);
            }
        }
    }
    result.append("  Process Pid override:\n");
    for (auto it = overridePidMapCopy.begin(); it != overridePidMapCopy.end(); ++it) {
        snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n",
            it->first, it->second);
        result.append(buffer);
    }
    result.append("  Events logs (most recent at top):\n");
    result.append(serviceLog);

@@ -216,20 +205,35 @@ std::shared_ptr<ResourceManagerService> ResourceManagerService::Create() {
std::shared_ptr<ResourceManagerService> ResourceManagerService::Create(
        const sp<ProcessInfoInterface>& processInfo,
        const sp<SystemCallbackInterface>& systemResource) {
    std::shared_ptr<ResourceManagerService> service = nullptr;
    // If codec importance feature is on, create the refactored implementation.
    if (CodecFeatureFlags::codec_importance()) {
        return ::ndk::SharedRefBase::make<ResourceManagerServiceNew>(processInfo, systemResource);
        service = ::ndk::SharedRefBase::make<ResourceManagerServiceNew>(processInfo,
                                                                        systemResource);
    } else {
        service = ::ndk::SharedRefBase::make<ResourceManagerService>(processInfo,
                                                                     systemResource);
    }

    if (service != nullptr) {
        service->init();
    }
    return ::ndk::SharedRefBase::make<ResourceManagerService>(processInfo, systemResource);

    return service;
}

// TEST only function.
std::shared_ptr<ResourceManagerService> ResourceManagerService::CreateNew(
        const sp<ProcessInfoInterface>& processInfo,
        const sp<SystemCallbackInterface>& systemResource) {
    return ::ndk::SharedRefBase::make<ResourceManagerServiceNew>(processInfo, systemResource);
    std::shared_ptr<ResourceManagerService> service =
        ::ndk::SharedRefBase::make<ResourceManagerServiceNew>(processInfo, systemResource);
    service->init();
    return service;
}

void ResourceManagerService::init() {}

ResourceManagerService::~ResourceManagerService() {}

void ResourceManagerService::setObserverService(
@@ -701,6 +705,16 @@ bool ResourceManagerService::reclaimUnconditionallyFrom(
    return false;
}

bool ResourceManagerService::overridePid_l(int32_t originalPid, int32_t newPid) {
    mOverridePidMap.erase(originalPid);
    if (newPid != -1) {
        mOverridePidMap.emplace(originalPid, newPid);
        return true;
    }

    return false;
}

Status ResourceManagerService::overridePid(int originalPid, int newPid) {
    String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
            originalPid, newPid);
@@ -720,9 +734,7 @@ Status ResourceManagerService::overridePid(int originalPid, int newPid) {

    {
        std::scoped_lock lock{mLock};
        mOverridePidMap.erase(originalPid);
        if (newPid != -1) {
            mOverridePidMap.emplace(originalPid, newPid);
        if (overridePid_l(originalPid, newPid)) {
            mResourceManagerMetrics->addPid(newPid);
        }
    }
@@ -730,6 +742,29 @@ Status ResourceManagerService::overridePid(int originalPid, int newPid) {
    return Status::ok();
}

bool ResourceManagerService::overrideProcessInfo_l(
        const std::shared_ptr<IResourceManagerClient>& client,
        int pid,
        int procState,
        int oomScore) {
    removeProcessInfoOverride_l(pid);

    if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
        // Override value is rejected by ProcessInfo.
        return false;
    }

    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
                                .uid = 0,
                                .id = 0,
                                .name = "<unknown client>"};
    auto deathNotifier = DeathNotifier::Create(
        client, ref<ResourceManagerService>(), clientInfo, true);

    mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});
    return true;
}

Status ResourceManagerService::overrideProcessInfo(
        const std::shared_ptr<IResourceManagerClient>& client, int pid, int procState,
        int oomScore) {
@@ -750,23 +785,12 @@ Status ResourceManagerService::overrideProcessInfo(
    }

    std::scoped_lock lock{mLock};
    removeProcessInfoOverride_l(pid);

    if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
    if (!overrideProcessInfo_l(client, pid, procState, oomScore)) {
        // Override value is rejected by ProcessInfo.
        return Status::fromServiceSpecificError(BAD_VALUE);
    }

    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
                                .uid = 0,
                                .id = 0,
                                .name = "<unknown client>"};
    auto deathNotifier = DeathNotifier::Create(
        client, ref<ResourceManagerService>(), clientInfo, true);

    mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});

    return Status::ok();

}

void ResourceManagerService::removeProcessInfoOverride(int pid) {
@@ -872,11 +896,12 @@ Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t
    return Status::ok();
}

bool ResourceManagerService::getPriority_l(int pid, int* priority) {
bool ResourceManagerService::getPriority_l(int pid, int* priority) const {
    int newPid = pid;

    if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
        newPid = mOverridePidMap[pid];
    std::map<int, int>::const_iterator found = mOverridePidMap.find(pid);
    if (found != mOverridePidMap.end()) {
        newPid = found->second;
        ALOGD("getPriority_l: use override pid %d instead original pid %d",
                newPid, pid);
    }
@@ -1068,4 +1093,8 @@ long ResourceManagerService::getCurrentConcurrentPixelCount(int pid) const {
    return mResourceManagerMetrics->getCurrentConcurrentPixelCount(pid);
}

void ResourceManagerService::notifyClientReleased(const ClientInfoParcel& clientInfo) {
    mResourceManagerMetrics->notifyClientReleased(clientInfo);
}

} // namespace android
+75 −39
Original line number Diff line number Diff line
@@ -73,7 +73,8 @@ public:
            const sp<SystemCallbackInterface> &systemResource);
    virtual ~ResourceManagerService();

    void setObserverService(const std::shared_ptr<ResourceObserverService>& observerService);
    virtual void setObserverService(
            const std::shared_ptr<ResourceObserverService>& observerService);

    // IResourceManagerService interface
    Status config(const std::vector<MediaResourcePolicyParcel>& policies) override;
@@ -103,8 +104,6 @@ public:

    Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;

    Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);

    Status notifyClientCreated(const ClientInfoParcel& clientInfo) override;

    Status notifyClientStarted(const ClientConfigParcel& clientConfig) override;
@@ -113,23 +112,31 @@ public:

    Status notifyClientConfigChanged(const ClientConfigParcel& clientConfig) override;

protected:
    // To get notifications when a resource is added for the first time.
    void onFirstAdded(const MediaResourceParcel& res, uid_t uid);
    // To get notifications when a resource has been removed at last.
    void onLastRemoved(const MediaResourceParcel& res, uid_t uid);

    // Reclaims resources from |clients|. Returns true if reclaim succeeded
    // for all clients.
    bool reclaimUnconditionallyFrom(const std::vector<ClientInfo>& targetClients);

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

    // To notify the metrics about client being released.
    void notifyClientReleased(const ClientInfoParcel& clientInfo);

    virtual Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);

private:
    friend class ResourceManagerServiceTest;
    friend class ResourceManagerServiceTestBase;
    friend class DeathNotifier;
    friend class OverrideProcessInfoDeathNotifier;

    // Reclaims resources from |clients|. Returns true if reclaim succeeded
    // for all clients.
    bool reclaimUnconditionallyFrom(
        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(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.
@@ -137,51 +144,73 @@ private:
        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.
    bool getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
                                          MediaResource::SubType subType,
                                          ClientInfo& clientsInfo);

    // 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 adds
    // the result client to the given Vector.
    void getClientForResource_l(const ResourceRequestInfo& resourceRequestInfo,
                                std::vector<ClientInfo>& clientsInfo);

    void onFirstAdded(const MediaResourceParcel& res, uid_t uid);
    void onLastRemoved(const MediaResourceParcel& res, uid_t uid);
    // Eventually we want to phase out this implementation of IResourceManagerService
    // (ResourceManagerService) and replace that with the newer implementation
    // (ResourceManagerServiceNew).
    // So, marking the following methods as private virtual and for the newer implementation
    // to override is the easiest way to maintain both implementation.

    // Initializes the internal state of the ResourceManagerService
    virtual void init();

    // 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);

    virtual bool overridePid_l(int32_t originalPid, int32_t newPid);

    virtual bool overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient>& client,
                                       int pid, int procState, int oomScore);

    // Get priority from process's pid
    bool getPriority_l(int pid, int* priority);
    virtual bool getPriority_l(int pid, int* priority) const;

    // Gets lowest priority process that has the specified resource type.
    // Returns false if failed. The output parameters will remain unchanged if failed.
    virtual bool getLowestPriorityPid_l(MediaResource::Type type, MediaResource::SubType subType,
                                        int* lowestPriorityPid, int* lowestPriority);

    void removeProcessInfoOverride(int pid);
    // Removes the pid from the override map.
    virtual void removeProcessInfoOverride(int pid);

    // Get the client for given pid and the clientId from the map
    virtual std::shared_ptr<IResourceManagerClient> getClient(
        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);

    // 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);

    // Get the client for given pid and the clientId from the map
    std::shared_ptr<IResourceManagerClient> getClient(int pid, const int64_t& clientId) const;

    // Remove the client for given pid and the clientId from the map
    bool removeClient(int pid, const int64_t& clientId);

    // 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.
@@ -190,15 +219,22 @@ private:
    static std::shared_ptr<ResourceManagerService> CreateNew(
        const sp<ProcessInfoInterface>& processInfo,
        const sp<SystemCallbackInterface>& systemResource);
    // Returns a unmodifiable reference to the internal resource state as a map
    virtual const std::map<int, ResourceInfos>& getResourceMap() const {
        return mMap;
    }

protected:
    mutable std::mutex mLock;
    sp<ProcessInfoInterface> mProcessInfo;
    sp<SystemCallbackInterface> mSystemCB;
    sp<ServiceLog> mServiceLog;
    PidResourceInfosMap mMap;
    bool mSupportsMultipleSecureCodecs;
    bool mSupportsSecureWithNonSecureCodec;
    int32_t mCpuBoostCount;

private:
    PidResourceInfosMap mMap;
    struct ProcessInfoOverride {
        std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
        std::shared_ptr<IResourceManagerClient> client;
+151 −6

File changed.

Preview size limit exceeded, changes collapsed.

+60 −2
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@

namespace android {

class ResourceTracker;

//
// A newer implementation of IResourceManagerService, which
// eventually will replace the older implementation in ResourceManagerService.
@@ -66,8 +68,6 @@ public:

    Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;

    Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);

    Status notifyClientCreated(const ClientInfoParcel& clientInfo) override;

    Status notifyClientStarted(const ClientConfigParcel& clientConfig) override;
@@ -77,6 +77,64 @@ public:
    Status notifyClientConfigChanged(const ClientConfigParcel& clientConfig) override;

    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

    friend class ResourceTracker;

private:

    // Initializes the internal state of the ResourceManagerService
    void init() override;

    void setObserverService(
            const std::shared_ptr<ResourceObserverService>& observerService) 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 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;

    bool overridePid_l(int32_t originalPid, int32_t newPid) override;

    bool overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient>& client,
                               int pid, int procState, int oomScore) override;

    // 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(
        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;

    // Get all the resource status for dump
    void getResourceDump(std::string& resourceLog) const override;

    // Returns a unmodifiable reference to the internal resource state as a map
    const std::map<int, ResourceInfos>& getResourceMap() const override;

    Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid) override;

private:
    std::shared_ptr<ResourceTracker> mResourceTracker;
};

// ----------------------------------------------------------------------------
Loading