/*
**
** Copyright 2015, 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 "ResourceManagerService"
#include <utils/Log.h>

#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <cutils/sched_policy.h>
#include <media/MediaResourcePolicy.h>
#include <media/stagefright/foundation/ABase.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/ProcessInfo.h>
#include <mediautils/SchedulingPolicyService.h>

#include "IMediaResourceMonitor.h"
#include "ResourceManagerMetrics.h"
#include "ResourceObserverService.h"
#include "ServiceLog.h"

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;
            }
        }
    }
}

binder_status_t ResourceManagerService::dump(int fd, const char** /*args*/, uint32_t /*numArgs*/) {
    String8 result;

    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
        result.format("Permission Denial: "
                "can't dump ResourceManagerService from pid=%d, uid=%d\n",
                AIBinder_getCallingPid(),
                AIBinder_getCallingUid());
        write(fd, result.c_str(), result.size());
        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;
    }

    const size_t SIZE = 256;
    char buffer[SIZE];
    snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
    result.append(buffer);
    result.append("  Policies:\n");
    snprintf(buffer, SIZE, "    SupportsMultipleSecureCodecs: %d\n", supportsMultipleSecureCodecs);
    result.append(buffer);
    snprintf(buffer, SIZE, "    SupportsSecureWithNonSecureCodec: %d\n",
            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);

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

    write(fd, result.c_str(), result.size());
    return OK;
}

struct SystemCallbackImpl : public ResourceManagerService::SystemCallbackInterface {
    SystemCallbackImpl() : mClientToken(new BBinder()) {}

    virtual void noteStartVideo(int uid) override {
        BatteryNotifier::getInstance().noteStartVideo(uid);
    }
    virtual void noteStopVideo(int uid) override {
        BatteryNotifier::getInstance().noteStopVideo(uid);
    }
    virtual void noteResetVideo() override {
        BatteryNotifier::getInstance().noteResetVideo();
    }
    virtual bool requestCpusetBoost(bool enable) override {
        return android::requestCpusetBoost(enable, mClientToken);
    }

protected:
    virtual ~SystemCallbackImpl() {}

private:
    DISALLOW_EVIL_CONSTRUCTORS(SystemCallbackImpl);
    sp<IBinder> mClientToken;
};

ResourceManagerService::ResourceManagerService()
    : ResourceManagerService(new ProcessInfo(), new SystemCallbackImpl()) {}

ResourceManagerService::ResourceManagerService(const sp<ProcessInfoInterface> &processInfo,
        const sp<SystemCallbackInterface> &systemResource)
    : mProcessInfo(processInfo),
      mSystemCB(systemResource),
      mServiceLog(new ServiceLog()),
      mSupportsMultipleSecureCodecs(true),
      mSupportsSecureWithNonSecureCodec(true),
      mCpuBoostCount(0) {
    mSystemCB->noteResetVideo();
    // Create ResourceManagerMetrics that handles all the metrics.
    mResourceManagerMetrics = std::make_unique<ResourceManagerMetrics>(mProcessInfo);
}

//static
void ResourceManagerService::instantiate() {
    std::shared_ptr<ResourceManagerService> service = Create();
    binder_status_t status =
                        AServiceManager_addServiceWithFlags(
                        service->asBinder().get(), getServiceName(),
                        AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
    if (status != STATUS_OK) {
        return;
    }

    std::shared_ptr<ResourceObserverService> observerService =
            ResourceObserverService::instantiate();

    if (observerService != nullptr) {
        service->setObserverService(observerService);
    }
    // TODO: mediaserver main() is already starting the thread pool,
    // move this to mediaserver main() when other services in mediaserver
    // are converted to ndk-platform aidl.
    //ABinderProcess_startThreadPool();
}

std::shared_ptr<ResourceManagerService> ResourceManagerService::Create() {
    return Create(new ProcessInfo(), new SystemCallbackImpl());
}

std::shared_ptr<ResourceManagerService> ResourceManagerService::Create(
        const sp<ProcessInfoInterface>& processInfo,
        const sp<SystemCallbackInterface>& systemResource) {
    return ::ndk::SharedRefBase::make<ResourceManagerService>(processInfo, systemResource);
}

ResourceManagerService::~ResourceManagerService() {}

void ResourceManagerService::setObserverService(
        const std::shared_ptr<ResourceObserverService>& observerService) {
    mObserverService = observerService;
}

Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
    String8 log = String8::format("config(%s)", getString(policies).c_str());
    mServiceLog->add(log);

    std::scoped_lock lock{mLock};
    for (size_t i = 0; i < policies.size(); ++i) {
        const std::string &type = policies[i].type;
        const std::string &value = policies[i].value;
        if (type == MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs()) {
            mSupportsMultipleSecureCodecs = (value == "true");
        } else if (type == MediaResourcePolicy::kPolicySupportsSecureWithNonSecureCodec()) {
            mSupportsSecureWithNonSecureCodec = (value == "true");
        }
    }
    return Status::ok();
}

void ResourceManagerService::onFirstAdded(const MediaResourceParcel& resource, uid_t uid) {
    // first time added
    if (resource.type == MediaResource::Type::kCpuBoost
     && resource.subType == MediaResource::SubType::kUnspecifiedSubType) {
        // Request it on every new instance of kCpuBoost, as the media.codec
        // could have died, if we only do it the first time subsequent instances
        // never gets the boost.
        if (mSystemCB->requestCpusetBoost(true) != OK) {
            ALOGW("couldn't request cpuset boost");
        }
        mCpuBoostCount++;
    } else if (resource.type == MediaResource::Type::kBattery
            && (resource.subType == MediaResource::SubType::kHwVideoCodec
                || resource.subType == MediaResource::SubType::kSwVideoCodec)) {
        mSystemCB->noteStartVideo(uid);
    }
}

void ResourceManagerService::onLastRemoved(const MediaResourceParcel& resource, uid_t uid) {
    if (resource.type == MediaResource::Type::kCpuBoost
            && resource.subType == MediaResource::SubType::kUnspecifiedSubType
            && mCpuBoostCount > 0) {
        if (--mCpuBoostCount == 0) {
            mSystemCB->requestCpusetBoost(false);
        }
    } else if (resource.type == MediaResource::Type::kBattery
            && (resource.subType == MediaResource::SubType::kHwVideoCodec
                || resource.subType == MediaResource::SubType::kSwVideoCodec)) {
        mSystemCB->noteStopVideo(uid);
    }
}

Status ResourceManagerService::addResource(const ClientInfoParcel& clientInfo,
        const std::shared_ptr<IResourceManagerClient>& client,
        const std::vector<MediaResourceParcel>& resources) {
    int32_t pid = clientInfo.pid;
    int32_t uid = clientInfo.uid;
    int64_t clientId = clientInfo.id;
    String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
            pid, uid, (long long) clientId, getString(resources).c_str());
    mServiceLog->add(log);

    std::scoped_lock lock{mLock};
    if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
        pid_t callingPid = IPCThreadState::self()->getCallingPid();
        uid_t callingUid = IPCThreadState::self()->getCallingUid();
        ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
                __FUNCTION__, pid, uid, callingPid, callingUid);
        pid = callingPid;
        uid = callingUid;
    }
    ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
    ResourceInfo& info = getResourceInfoForEdit(clientInfo, client, infos);
    ResourceList resourceAdded;

    for (size_t i = 0; i < resources.size(); ++i) {
        const auto &res = resources[i];
        const auto resType = std::tuple(res.type, res.subType, res.id);

        if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
            ALOGW("Ignoring request to remove negative value of non-drm resource");
            continue;
        }
        if (info.resources.find(resType) == info.resources.end()) {
            if (res.value <= 0) {
                // We can't init a new entry with negative value, although it's allowed
                // to merge in negative values after the initial add.
                ALOGW("Ignoring request to add new resource entry with value <= 0");
                continue;
            }
            onFirstAdded(res, info.uid);
            info.resources[resType] = res;
        } else {
            mergeResources(info.resources[resType], res);
        }
        // Add it to the list of added resources for observers.
        auto it = resourceAdded.find(resType);
        if (it == resourceAdded.end()) {
            resourceAdded[resType] = res;
        } else {
            mergeResources(it->second, res);
        }
    }
    if (info.deathNotifier == nullptr && client != nullptr) {
        info.deathNotifier = DeathNotifier::Create(
            client, ref<ResourceManagerService>(), clientInfo);
    }
    if (mObserverService != nullptr && !resourceAdded.empty()) {
        mObserverService->onResourceAdded(uid, pid, resourceAdded);
    }
    notifyResourceGranted(pid, resources);

    return Status::ok();
}

Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
        const std::vector<MediaResourceParcel>& resources) {
    int32_t pid = clientInfo.pid;
    int32_t uid = clientInfo.uid;
    int64_t clientId = clientInfo.id;
    String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
            pid, uid, (long long) clientId, getString(resources).c_str());
    mServiceLog->add(log);

    std::scoped_lock lock{mLock};
    if (!mProcessInfo->isPidTrusted(pid)) {
        pid_t callingPid = IPCThreadState::self()->getCallingPid();
        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                pid, callingPid);
        pid = callingPid;
    }
    PidResourceInfosMap::iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
        return Status::ok();
    }
    ResourceInfos& infos = found->second;

    ResourceInfos::iterator foundClient = infos.find(clientId);
    if (foundClient == infos.end()) {
        ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
        return Status::ok();
    }

    ResourceInfo& info = foundClient->second;
    ResourceList resourceRemoved;
    for (size_t i = 0; i < resources.size(); ++i) {
        const auto &res = resources[i];
        const auto resType = std::tuple(res.type, res.subType, res.id);

        if (res.value < 0) {
            ALOGW("Ignoring request to remove negative value of resource");
            continue;
        }
        // ignore if we don't have it
        if (info.resources.find(resType) != info.resources.end()) {
            MediaResourceParcel &resource = info.resources[resType];
            MediaResourceParcel actualRemoved = res;
            if (resource.value > res.value) {
                resource.value -= res.value;
            } else {
                onLastRemoved(res, info.uid);
                actualRemoved.value = resource.value;
                info.resources.erase(resType);
            }

            // Add it to the list of removed resources for observers.
            auto it = resourceRemoved.find(resType);
            if (it == resourceRemoved.end()) {
                resourceRemoved[resType] = actualRemoved;
            } else {
                mergeResources(it->second, actualRemoved);
            }
        }
    }
    if (mObserverService != nullptr && !resourceRemoved.empty()) {
        mObserverService->onResourceRemoved(info.uid, pid, resourceRemoved);
    }
    return Status::ok();
}

Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
    removeResource(clientInfo, true /*checkValid*/);
    return Status::ok();
}

Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
    int32_t pid = clientInfo.pid;
    int32_t uid = clientInfo.uid;
    int64_t clientId = clientInfo.id;
    String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
            pid, uid, (long long) clientId);
    mServiceLog->add(log);

    std::scoped_lock lock{mLock};
    if (checkValid && !mProcessInfo->isPidTrusted(pid)) {
        pid_t callingPid = IPCThreadState::self()->getCallingPid();
        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                pid, callingPid);
        pid = callingPid;
    }
    PidResourceInfosMap::iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
        return Status::ok();
    }
    ResourceInfos& infos = found->second;

    ResourceInfos::iterator foundClient = infos.find(clientId);
    if (foundClient == infos.end()) {
        ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
        return Status::ok();
    }

    const ResourceInfo& info = foundClient->second;
    for (auto it = info.resources.begin(); it != info.resources.end(); it++) {
        onLastRemoved(it->second, info.uid);
    }

    // Since this client has been removed, update the metrics collector.
    mResourceManagerMetrics->notifyClientReleased(clientInfo);

    if (mObserverService != nullptr && !info.resources.empty()) {
        mObserverService->onResourceRemoved(info.uid, pid, info.resources);
    }

    infos.erase(foundClient);
    return Status::ok();
}

void ResourceManagerService::getClientForResource_l(
        const ResourceRequestInfo& resourceRequestInfo,
        std::vector<ClientInfo>& clientsInfo) {
    int callingPid = resourceRequestInfo.mCallingPid;
    const MediaResourceParcel* res = resourceRequestInfo.mResource;
    if (res == NULL) {
        return;
    }

    // Before looking into other processes, check if we have clients marked for
    // pending removal in the same process.
    ClientInfo clientInfo;
    if (getBiggestClientPendingRemoval_l(callingPid, res->type, res->subType, clientInfo)) {
        clientsInfo.emplace_back(clientInfo);
        return;
    }

    // Now find client(s) from a lowest priority process that has needed resources.
    if (getLowestPriorityBiggestClient_l(resourceRequestInfo, clientInfo)) {
        clientsInfo.push_back(clientInfo);
    }
}

Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
        const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
    int32_t callingPid = clientInfo.pid;
    std::string clientName = clientInfo.name;
    String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
            callingPid, clientInfo.uid, getString(resources).c_str());
    mServiceLog->add(log);
    *_aidl_return = false;

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

    *_aidl_return = reclaimUnconditionallyFrom(targetClients);

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

    return Status::ok();
}

void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
                                             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 (const ClientInfo& targetClient : targetClients) {
        int targetPriority = -1;
        getPriority_l(targetClient.mPid, &targetPriority);
        priorities.push_back(targetPriority);
    }
    mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, targetClients, reclaimed);
}

std::shared_ptr<IResourceManagerClient> ResourceManagerService::getClient(
        int pid, const int64_t& clientId) const {
    std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
        return nullptr;
    }

    const ResourceInfos& infos = found->second;
    ResourceInfos::const_iterator foundClient = infos.find(clientId);
    if (foundClient == infos.end()) {
        ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
        return nullptr;
    }

    return foundClient->second.client;
}

bool ResourceManagerService::removeClient(int pid, const int64_t& clientId) {
    std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
        return false;
    }

    ResourceInfos& infos = found->second;
    ResourceInfos::iterator foundClient = infos.find(clientId);
    if (foundClient == infos.end()) {
        ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
        return false;
    }

    infos.erase(foundClient);
    return true;
}

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

    int64_t failedClientId = -1;
    int32_t failedClientPid = -1;
    for (const ClientInfo& targetClient : targetClients) {
        std::shared_ptr<IResourceManagerClient> client = getClient(
            targetClient.mPid, targetClient.mClientId);
        if (client == nullptr) {
            // skip already released clients.
            continue;
        }
        String8 log = String8::format("reclaimResource from client %p", client.get());
        mServiceLog->add(log);
        bool success;
        Status status = client->reclaimResource(&success);
        if (!status.isOk() || !success) {
            failedClientId = targetClient.mClientId;
            failedClientPid = targetClient.mPid;
            break;
        }
    }

    if (failedClientId == -1) {
        return true;
    }

    {
        std::scoped_lock lock{mLock};
        bool found = removeClient(failedClientPid, failedClientId);
        if (found) {
            ALOGW("Failed to reclaim resources from client with pid %d", failedClientPid);
        } else {
            ALOGW("Failed to reclaim resources from unlocateable client");
        }
    }

    return false;
}

Status ResourceManagerService::overridePid(int originalPid, int newPid) {
    String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
            originalPid, newPid);
    mServiceLog->add(log);

    // allow if this is called from the same process or the process has
    // permission.
    if ((AIBinder_getCallingPid() != getpid()) &&
        (checkCallingPermission(String16(
             "android.permission.MEDIA_RESOURCE_OVERRIDE_PID")) == false)) {
      ALOGE(
          "Permission Denial: can't access overridePid method from pid=%d, "
          "self pid=%d\n",
          AIBinder_getCallingPid(), getpid());
      return Status::fromServiceSpecificError(PERMISSION_DENIED);
    }

    {
        std::scoped_lock lock{mLock};
        mOverridePidMap.erase(originalPid);
        if (newPid != -1) {
            mOverridePidMap.emplace(originalPid, newPid);
            mResourceManagerMetrics->addPid(newPid);
        }
    }

    return Status::ok();
}

Status ResourceManagerService::overrideProcessInfo(
        const std::shared_ptr<IResourceManagerClient>& client, int pid, int procState,
        int oomScore) {
    String8 log = String8::format("overrideProcessInfo(pid %d, procState %d, oomScore %d)",
            pid, procState, oomScore);
    mServiceLog->add(log);

    // Only allow the override if the caller already can access process state and oom scores.
    int callingPid = AIBinder_getCallingPid();
    if (callingPid != getpid() && (callingPid != pid || !checkCallingPermission(String16(
            "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE")))) {
        ALOGE("Permission Denial: overrideProcessInfo method from pid=%d", callingPid);
        return Status::fromServiceSpecificError(PERMISSION_DENIED);
    }

    if (client == nullptr) {
        return Status::fromServiceSpecificError(BAD_VALUE);
    }

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

    if (!mProcessInfo->overrideProcessInfo(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) {
    std::scoped_lock lock{mLock};

    removeProcessInfoOverride_l(pid);
}

void ResourceManagerService::removeProcessInfoOverride_l(int pid) {
    auto it = mProcessInfoOverrideMap.find(pid);
    if (it == mProcessInfoOverrideMap.end()) {
        return;
    }

    mProcessInfo->removeProcessInfoOverride(pid);
    mProcessInfoOverrideMap.erase(pid);
}

Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
    int32_t pid = clientInfo.pid;
    int64_t clientId = clientInfo.id;
    String8 log = String8::format(
            "markClientForPendingRemoval(pid %d, clientId %lld)",
            pid, (long long) clientId);
    mServiceLog->add(log);

    std::scoped_lock lock{mLock};
    if (!mProcessInfo->isPidTrusted(pid)) {
        pid_t callingPid = IPCThreadState::self()->getCallingPid();
        ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                pid, callingPid);
        pid = callingPid;
    }
    PidResourceInfosMap::iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld",
              pid, (long long)clientId);
        return Status::ok();
    }
    ResourceInfos& infos = found->second;

    ResourceInfos::iterator foundClient = infos.find(clientId);
    if (foundClient == infos.end()) {
        ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId);
        return Status::ok();
    }

    ResourceInfo& info = foundClient->second;
    info.pendingRemoval = true;
    return Status::ok();
}

Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
    String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
    mServiceLog->add(log);

    std::vector<ClientInfo> targetClients;
    {
        std::scoped_lock lock{mLock};
        if (!mProcessInfo->isPidTrusted(pid)) {
            pid_t callingPid = IPCThreadState::self()->getCallingPid();
            ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
                    pid, callingPid);
            pid = callingPid;
        }

        for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
                                         MediaResource::Type::kNonSecureCodec,
                                         MediaResource::Type::kGraphicMemory,
                                         MediaResource::Type::kDrmSession}) {
            switch (type) {
                // Codec resources are segregated by audio, video and image domains.
                case MediaResource::Type::kSecureCodec:
                case MediaResource::Type::kNonSecureCodec:
                    for (MediaResource::SubType subType : {MediaResource::SubType::kHwAudioCodec,
                                                           MediaResource::SubType::kSwAudioCodec,
                                                           MediaResource::SubType::kHwVideoCodec,
                                                           MediaResource::SubType::kSwVideoCodec,
                                                           MediaResource::SubType::kHwImageCodec,
                                                           MediaResource::SubType::kSwImageCodec}) {
                        ClientInfo clientInfo;
                        if (getBiggestClientPendingRemoval_l(pid, type, subType, clientInfo)) {
                            targetClients.emplace_back(clientInfo);
                            continue;
                        }
                    }
                    break;
                // Non-codec resources are shared by audio, video and image codecs (no subtype).
                default:
                    ClientInfo clientInfo;
                    if (getBiggestClientPendingRemoval_l(pid, type,
                            MediaResource::SubType::kUnspecifiedSubType, clientInfo)) {
                        targetClients.emplace_back(clientInfo);
                    }
                    break;
            }
        }
    }

    if (!targetClients.empty()) {
        reclaimUnconditionallyFrom(targetClients);
    }
    return Status::ok();
}

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

    if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
        newPid = mOverridePidMap[pid];
        ALOGD("getPriority_l: use override pid %d instead original pid %d",
                newPid, pid);
    }

    return mProcessInfo->getPriority(newPid, priority);
}

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(resourceRequestInfo.mCallingPid, pid)) {
                    // some higher/equal priority process owns the resource,
                    // this request can't be fulfilled.
                    ALOGE("%s: can't reclaim resource %s from pid %d",
                          __func__, asString(type), pid);
                    clientsInfo.clear();
                    return false;
                }
                clientsInfo.emplace_back(pid, info.uid, info.clientId);
            }
        }
    }
    if (clientsInfo.size() == 0) {
        ALOGV("%s: didn't find any resource %s", __func__, asString(type));
    }
    return true;
}

// 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 ResourceManagerService::getLowestPriorityBiggestClient_l(
        const ResourceRequestInfo& resourceRequestInfo,
        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 (!getPriority_l(callingPid, &callingPriority)) {
        ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
        return false;
    }
    if (!getLowestPriorityPid_l(type, subType, &lowestPriorityPid, &lowestPriority)) {
        return false;
    }
    if (lowestPriority <= callingPriority) {
        ALOGE("%s: lowest priority %d vs caller priority %d",
              __func__, lowestPriority, callingPriority);
        return false;
    }

    if (!getBiggestClient_l(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 ResourceManagerService::getLowestPriorityPid_l(MediaResource::Type type,
        MediaResource::SubType subType, int *lowestPriorityPid, int *lowestPriority) {
    int pid = -1;
    int priority = -1;
    for (auto& [tempPid, infos] : mMap) {
        if (infos.size() == 0) {
            // no client on this process.
            continue;
        }
        if (!hasResourceType(type, subType, infos)) {
            // doesn't have the requested resource type
            continue;
        }
        int tempPriority = -1;
        if (!getPriority_l(tempPid, &tempPriority)) {
            ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
            // TODO: remove this pid from mMap?
            continue;
        }
        if (pid == -1 || tempPriority > priority) {
            // initial the value
            pid = tempPid;
            priority = tempPriority;
        }
    }
    if (pid != -1) {
        *lowestPriorityPid = pid;
        *lowestPriority = priority;
    }
    return (pid != -1);
}

bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
    int callingPidPriority;
    if (!getPriority_l(callingPid, &callingPidPriority)) {
        return false;
    }

    int priority;
    if (!getPriority_l(pid, &priority)) {
        return false;
    }

    return (callingPidPriority < priority);
}

bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
        MediaResource::SubType subType, ClientInfo& clientInfo) {
    return getBiggestClient_l(pid, type, subType, clientInfo, true /* pendingRemovalOnly */);
}

bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
        MediaResource::SubType subType, ClientInfo& clientInfo, bool pendingRemovalOnly) {
    PidResourceInfosMap::iterator found = mMap.find(pid);
    if (found == mMap.end()) {
        ALOGE_IF(!pendingRemovalOnly,
                 "getBiggestClient_l: can't find resource info for pid %d", 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;
        if (pendingRemovalOnly && !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) {
        ALOGE_IF(!pendingRemovalOnly,
                 "getBiggestClient_l: can't find resource type %s and subtype %s for pid %d",
                 asString(type), asString(subType), pid);
        return false;
    }

    clientInfo.mPid = pid;
    clientInfo.mUid = uid;
    clientInfo.mClientId = clientId;
    return true;
}

Status ResourceManagerService::notifyClientCreated(const ClientInfoParcel& clientInfo) {
    mResourceManagerMetrics->notifyClientCreated(clientInfo);
    return Status::ok();
}

Status ResourceManagerService::notifyClientStarted(const ClientConfigParcel& clientConfig) {
    mResourceManagerMetrics->notifyClientStarted(clientConfig);
    return Status::ok();
}

Status ResourceManagerService::notifyClientStopped(const ClientConfigParcel& clientConfig) {
    mResourceManagerMetrics->notifyClientStopped(clientConfig);
    return Status::ok();
}

Status ResourceManagerService::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
    mResourceManagerMetrics->notifyClientConfigChanged(clientConfig);
    return Status::ok();
}

long ResourceManagerService::getPeakConcurrentPixelCount(int pid) const {
    return mResourceManagerMetrics->getPeakConcurrentPixelCount(pid);
}

long ResourceManagerService::getCurrentConcurrentPixelCount(int pid) const {
    return mResourceManagerMetrics->getCurrentConcurrentPixelCount(pid);
}

} // namespace android
