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

Commit 271429db authored by Wonsik Kim's avatar Wonsik Kim
Browse files

MediaCodec: clean up resources pending removal at init

Until we can track memory usage in ResourceManager, always clean up
resources pending removal at init so that we can reclaim memory
and any other resources that are untracked.

Bug: 169398817
Test: atest ResourceManagerService_test
Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small
Change-Id: Ia515443379edb03e68dd2ff5cba07c405aacd433
parent e53a2243
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -102,4 +102,11 @@ interface IResourceManagerService {
     * @param clientId clientId within the pid that will be removed.
     */
    void markClientForPendingRemoval(int pid, long clientId);

    /**
     * Reclaim resources from clients pending removal, if any.
     *
     * @param pid pid from which resources will be reclaimed.
     */
    void reclaimResourcesFromClientsPendingRemoval(int pid);
}
+3 −0
Original line number Diff line number Diff line
@@ -241,6 +241,9 @@ void MediaCodec::ResourceManagerServiceProxy::init() {
    }

    AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);

    // Kill clients pending removal.
    mService->reclaimResourcesFromClientsPendingRemoval(mPid);
}

//static
+45 −7
Original line number Diff line number Diff line
@@ -575,13 +575,19 @@ Status ResourceManagerService::reclaimResource(
        }
    }

    if (clients.size() == 0) {
    *_aidl_return = reclaimInternal(clients);
    return Status::ok();
}

bool ResourceManagerService::reclaimInternal(
        const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
    if (clients.size() == 0) {
        return false;
    }

    std::shared_ptr<IResourceManagerClient> failedClient;
    for (size_t i = 0; i < clients.size(); ++i) {
        log = String8::format("reclaimResource from client %p", clients[i].get());
        String8 log = String8::format("reclaimResource from client %p", clients[i].get());
        mServiceLog->add(log);
        bool success;
        Status status = clients[i]->reclaimResource(&success);
@@ -592,8 +598,7 @@ Status ResourceManagerService::reclaimResource(
    }

    if (failedClient == NULL) {
        *_aidl_return = true;
        return Status::ok();
        return true;
    }

    {
@@ -618,7 +623,7 @@ Status ResourceManagerService::reclaimResource(
        }
    }

    return Status::ok();
    return false;
}

Status ResourceManagerService::overridePid(
@@ -681,6 +686,36 @@ Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t
    return Status::ok();
}

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

    Vector<std::shared_ptr<IResourceManagerClient>> clients;
    {
        Mutex::Autolock lock(mLock);
        if (!mProcessInfo->isValidPid(pid)) {
            ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid.");
            return Status::fromServiceSpecificError(BAD_VALUE);
        }

        for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
                                         MediaResource::Type::kNonSecureCodec,
                                         MediaResource::Type::kGraphicMemory,
                                         MediaResource::Type::kDrmSession}) {
            std::shared_ptr<IResourceManagerClient> client;
            if (getBiggestClient_l(pid, type, &client, true /* pendingRemovalOnly */)) {
                clients.add(client);
                break;
            }
        }
    }

    if (!clients.empty()) {
        reclaimInternal(clients);
    }
    return Status::ok();
}

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

@@ -804,7 +839,8 @@ bool ResourceManagerService::getBiggestClient_l(
        bool pendingRemovalOnly) {
    ssize_t index = mMap.indexOfKey(pid);
    if (index < 0) {
        ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
        ALOGE_IF(!pendingRemovalOnly,
                 "getBiggestClient_l: can't find resource info for pid %d", pid);
        return false;
    }

@@ -828,7 +864,9 @@ bool ResourceManagerService::getBiggestClient_l(
    }

    if (clientTemp == NULL) {
        ALOGE("getBiggestClient_l: can't find resource type %s for pid %d", asString(type), pid);
        ALOGE_IF(!pendingRemovalOnly,
                 "getBiggestClient_l: can't find resource type %s for pid %d",
                 asString(type), pid);
        return false;
    }

+7 −0
Original line number Diff line number Diff line
@@ -127,11 +127,18 @@ public:

    Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;

    Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;

    Status removeResource(int pid, int64_t clientId, bool checkValid);

private:
    friend class ResourceManagerServiceTest;

    // Reclaims resources from |clients|. Returns true if reclaim succeeded
    // for all clients.
    bool reclaimInternal(
            const Vector<std::shared_ptr<IResourceManagerClient>> &clients);

    // 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.
+24 −0
Original line number Diff line number Diff line
@@ -520,6 +520,30 @@ protected:
            // clean up client 3 which still left
            mService->removeClient(kTestPid2, getId(mTestClient3));
        }

        {
            addResource();
            mService->mSupportsSecureWithNonSecureCodec = true;

            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));

            // client marked for pending removal got reclaimed
            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);

            // No more clients marked for removal
            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
            verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);

            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));

            // client marked for pending removal got reclaimed
            EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
            verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);

            // clean up client 1 which still left
            mService->removeClient(kTestPid1, getId(mTestClient1));
        }
    }

    void testRemoveClient() {