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

Commit 6b31ef27 authored by Devin Moore's avatar Devin Moore
Browse files

Add API to binder to set min threads

If an RpcServer has a rootObject that requires a minimum number of
threads that is less than its mMaxThreads, it will overwrite the
mMaxThreads with this minimum thread number.

This is intended to avoid the need to expose RpcServer and its
implementation details in higher layers like ndk and rust.

This is only used for interactions with RpcServers right now.

Flag: EXEMPT adding new API, not using it
Test: atest binderRpcTest
Bug: 430314963
Change-Id: I3bb674d4c68483243c4a4b89cbb4c827b6c59e70
parent b18c8f50
Loading
Loading
Loading
Loading
+39 −0
Original line number Original line Diff line number Diff line
@@ -238,6 +238,22 @@ sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func m
    return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
    return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
}
}


void IBinder::setMinRpcThreads(uint16_t min) {
    if (BBinder* local = this->localBinder(); local != nullptr) {
        local->setMinRpcThreads(min);
    } else {
        LOG_ALWAYS_FATAL("setMinRpcThreads only works for local BBinders.");
    }
}

uint16_t IBinder::getMinRpcThreads() {
    if (BBinder* local = this->localBinder(); local != nullptr) {
        return local->getMinRpcThreads();
    } else {
        LOG_ALWAYS_FATAL("getMinRpcThreads only works for local BBinders.");
    }
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


class BBinder::RpcServerLink : public IBinder::DeathRecipient {
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -273,6 +289,8 @@ private:
};
};
BBinder::RpcServerLink::~RpcServerLink() {}
BBinder::RpcServerLink::~RpcServerLink() {}


static constexpr uint16_t kDefaultMinThreads = 1;

class BBinder::Extras
class BBinder::Extras
{
{
public:
public:
@@ -289,6 +307,7 @@ public:
    RpcMutex mLock;
    RpcMutex mLock;
    std::set<sp<RpcServerLink>> mRpcServerLinks;
    std::set<sp<RpcServerLink>> mRpcServerLinks;
    BpBinder::ObjectManager mObjectMgr;
    BpBinder::ObjectManager mObjectMgr;
    uint16_t mMinThreads = kDefaultMinThreads;


    unique_fd mRecordingFd;
    unique_fd mRecordingFd;
};
};
@@ -630,6 +649,26 @@ void BBinder::setInheritRt(bool inheritRt) {
    e->mInheritRt = inheritRt;
    e->mInheritRt = inheritRt;
}
}


void BBinder::setMinRpcThreads(uint16_t min) {
    LOG_ALWAYS_FATAL_IF(mParceled,
                        "setMinRpcThreads() should not be called after a binder object "
                        "is parceled/sent to another process");
    Extras* e = mExtras.load(std::memory_order_acquire);
    if (!e) {
        e = getOrCreateExtras();
        if (!e) return; // out of memory
    }
    e->mMinThreads = min;
}

uint16_t BBinder::getMinRpcThreads() const {
    Extras* e = mExtras.load(std::memory_order_acquire);
    if (!e) {
        return kDefaultMinThreads;
    }
    return e->mMinThreads;
}

std::atomic<bool> BBinder::sGlobalInheritRt(false);
std::atomic<bool> BBinder::sGlobalInheritRt(false);


void BBinder::setGlobalInheritRt(bool enabled) {
void BBinder::setGlobalInheritRt(bool enabled) {
+29 −1
Original line number Original line Diff line number Diff line
@@ -132,6 +132,13 @@ status_t RpcServer::setupInetServer(const char* address, unsigned int port,
void RpcServer::setMaxThreads(size_t threads) {
void RpcServer::setMaxThreads(size_t threads) {
    LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads");
    LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads");
    LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running");
    LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running");
    if (sp<IBinder> root = getRootObject(); root != nullptr) {
        LOG_ALWAYS_FATAL_IF(threads < root->getMinRpcThreads(),
                            "RpcServer can not satisfy the root object's minimum "
                            "thread requirements of %d with the requested max "
                            "thread count of %zu",
                            root->getMinRpcThreads(), threads);
    }
    mMaxThreads = threads;
    mMaxThreads = threads;
}
}


@@ -156,10 +163,25 @@ void RpcServer::setSupportedFileDescriptorTransportModes(
    }
    }
}
}


static void logMaxThreadOverwrite(size_t max, uint16_t min, bool isPerSession) {
    ALOGW("Overriding this RpcServer's max threads (%zu) based on the min threads required "
          "(%d) by the %s object that is being set.",
          max, min, isPerSession ? "per-session root" : "root");
}

void RpcServer::maybeOverwriteMaxThreads(const sp<IBinder>& binder) {
    uint16_t minThreads = binder->getMinRpcThreads();
    if (mMaxThreads < minThreads) {
        logMaxThreadOverwrite(mMaxThreads, minThreads, false);
        mMaxThreads = binder->getMinRpcThreads();
    }
}

void RpcServer::setRootObject(const sp<IBinder>& binder) {
void RpcServer::setRootObject(const sp<IBinder>& binder) {
    RpcMutexLockGuard _l(mLock);
    RpcMutexLockGuard _l(mLock);
    mRootObjectFactory = nullptr;
    mRootObjectFactory = nullptr;
    mRootObjectWeak = mRootObject = binder;
    mRootObjectWeak = mRootObject = binder;
    maybeOverwriteMaxThreads(binder);
}
}


void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
@@ -167,6 +189,10 @@ void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
    mRootObject.clear();
    mRootObject.clear();
    mRootObjectFactory = nullptr;
    mRootObjectFactory = nullptr;
    mRootObjectWeak = binder;
    mRootObjectWeak = binder;

    sp<IBinder> s = binder.promote();
    if (s == nullptr) return;
    maybeOverwriteMaxThreads(s);
}
}
void RpcServer::setPerSessionRootObject(
void RpcServer::setPerSessionRootObject(
        std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& makeObject) {
        std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& makeObject) {
@@ -518,7 +544,6 @@ void RpcServer::establishConnection(
            } while (server->mSessions.end() != server->mSessions.find(sessionId));
            } while (server->mSessions.end() != server->mSessions.find(sessionId));


            session = sp<RpcSession>::make(nullptr);
            session = sp<RpcSession>::make(nullptr);
            session->setMaxIncomingThreads(server->mMaxThreads);
            if (!session->setProtocolVersion(protocolVersion)) return;
            if (!session->setProtocolVersion(protocolVersion)) return;


            if (header.fileDescriptorTransportMode <
            if (header.fileDescriptorTransportMode <
@@ -541,8 +566,11 @@ void RpcServer::establishConnection(
                        server->mRootObjectFactory(wp<RpcSession>(session), addr.data(), addrLen);
                        server->mRootObjectFactory(wp<RpcSession>(session), addr.data(), addrLen);
                if (sessionSpecificRoot == nullptr) {
                if (sessionSpecificRoot == nullptr) {
                    ALOGE("Warning: server returned null from root object factory");
                    ALOGE("Warning: server returned null from root object factory");
                } else {
                    server->maybeOverwriteMaxThreads(sessionSpecificRoot);
                }
                }
            }
            }
            session->setMaxIncomingThreads(server->mMaxThreads);


            if (!session->setForServer(server, server, sessionId, sessionSpecificRoot)) {
            if (!session->setForServer(server, server, sessionId, sessionSpecificRoot)) {
                ALOGE("Failed to attach server to session");
                ALOGE("Failed to attach server to session");
+5 −0
Original line number Original line Diff line number Diff line
@@ -91,6 +91,11 @@ public:
    // This must be called before the object is sent to another process. Not thread safe.
    // This must be called before the object is sent to another process. Not thread safe.
    LIBBINDER_EXPORTED void setInheritRt(bool inheritRt);
    LIBBINDER_EXPORTED void setInheritRt(bool inheritRt);


    // Default is 1. This is configured for each RpcSession attached to each
    // BBinder object in an RpcServer.
    LIBBINDER_EXPORTED void setMinRpcThreads(uint16_t min);
    LIBBINDER_EXPORTED uint16_t getMinRpcThreads() const;

    // Set default, overridden by setInheritRt. You must set this default early.
    // Set default, overridden by setInheritRt. You must set this default early.
    // Any binder objects sent out of the process before this is called will
    // Any binder objects sent out of the process before this is called will
    // not use the updated value.
    // not use the updated value.
+2 −0
Original line number Original line Diff line number Diff line
@@ -344,6 +344,8 @@ public:
    typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
    typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
    sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
    sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
                                   const void* makeArgs);
                                   const void* makeArgs);
    void setMinRpcThreads(uint16_t min);
    uint16_t getMinRpcThreads();


protected:
protected:
    virtual          ~IBinder();
    virtual          ~IBinder();
+2 −0
Original line number Original line Diff line number Diff line
@@ -271,6 +271,8 @@ private:


    const std::unique_ptr<RpcTransportCtx> mCtx;
    const std::unique_ptr<RpcTransportCtx> mCtx;
    size_t mMaxThreads = 1;
    size_t mMaxThreads = 1;
    // overwrite mMaxThreads if the binder has min threads to something larger
    void maybeOverwriteMaxThreads(const sp<IBinder>& binder);
    std::optional<uint32_t> mProtocolVersion;
    std::optional<uint32_t> mProtocolVersion;
    // A mode is supported if the N'th bit is on, where N is the mode enum's value.
    // A mode is supported if the N'th bit is on, where N is the mode enum's value.
    std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set(
    std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set(
Loading