Merge "Make available to com.android.compos apex"
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/bugreport/OWNERS
+++ b/cmds/bugreport/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/bugreportz/OWNERS
+++ b/cmds/bugreportz/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index 2a9b681..5f56531 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -1,4 +1,5 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 4f6a89e..97a63ca 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -1,5 +1,6 @@
 set noparent
 
+gavincorkery@google.com
 nandana@google.com
 jsharkey@android.com
 
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
index fc745d0..d6807ff 100644
--- a/cmds/installd/OWNERS
+++ b/cmds/installd/OWNERS
@@ -9,3 +9,4 @@
 ngeoffray@google.com
 rpl@google.com
 toddke@google.com
+patb@google.com
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index ef7fd44..18b77e6 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -366,19 +366,45 @@
 
 pid_t IPCThreadState::getCallingPid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingPid;
 }
 
 const char* IPCThreadState::getCallingSid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingSid;
 }
 
 uid_t IPCThreadState::getCallingUid() const
 {
+    checkContextIsBinderForUse(__func__);
     return mCallingUid;
 }
 
+IPCThreadState::SpGuard* IPCThreadState::pushGetCallingSpGuard(SpGuard* guard) {
+    SpGuard* orig = mServingStackPointerGuard;
+    mServingStackPointerGuard = guard;
+    return orig;
+}
+
+void IPCThreadState::restoreGetCallingSpGuard(SpGuard* guard) {
+    mServingStackPointerGuard = guard;
+}
+
+void IPCThreadState::checkContextIsBinderForUse(const char* use) const {
+    if (mServingStackPointerGuard == nullptr) return;
+
+    if (!mServingStackPointer || mServingStackPointerGuard < mServingStackPointer) {
+        LOG_ALWAYS_FATAL("In context %s, %s does not make sense.",
+                         mServingStackPointerGuard->context, use);
+    }
+
+    // in the case mServingStackPointer is deeper in the stack than the guard,
+    // we must be serving a binder transaction (maybe nested). This is a binder
+    // context, so we don't abort
+}
+
 int64_t IPCThreadState::clearCallingIdentity()
 {
     // ignore mCallingSid for legacy reasons
@@ -847,15 +873,15 @@
 }
 
 IPCThreadState::IPCThreadState()
-    : mProcess(ProcessState::self()),
-      mServingStackPointer(nullptr),
-      mWorkSource(kUnsetWorkSource),
-      mPropagateWorkSource(false),
-      mIsLooper(false),
-      mStrictModePolicy(0),
-      mLastTransactionBinderFlags(0),
-      mCallRestriction(mProcess->mCallRestriction)
-{
+      : mProcess(ProcessState::self()),
+        mServingStackPointer(nullptr),
+        mServingStackPointerGuard(nullptr),
+        mWorkSource(kUnsetWorkSource),
+        mPropagateWorkSource(false),
+        mIsLooper(false),
+        mStrictModePolicy(0),
+        mLastTransactionBinderFlags(0),
+        mCallRestriction(mProcess->mCallRestriction) {
     pthread_setspecific(gTLS, this);
     clearCaller();
     mIn.setDataCapacity(256);
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index c0cdcd6..9cc6e7f 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -22,6 +22,7 @@
 #include <thread>
 #include <vector>
 
+#include <android-base/scopeguard.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
 #include <log/log.h>
@@ -32,6 +33,7 @@
 
 namespace android {
 
+using base::ScopeGuard;
 using base::unique_fd;
 
 RpcServer::RpcServer() {}
@@ -107,65 +109,51 @@
 
 void RpcServer::setRootObject(const sp<IBinder>& binder) {
     std::lock_guard<std::mutex> _l(mLock);
-    mRootObject = binder;
+    mRootObjectWeak = mRootObject = binder;
+}
+
+void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
+    std::lock_guard<std::mutex> _l(mLock);
+    mRootObject.clear();
+    mRootObjectWeak = binder;
 }
 
 sp<IBinder> RpcServer::getRootObject() {
     std::lock_guard<std::mutex> _l(mLock);
-    return mRootObject;
+    bool hasWeak = mRootObjectWeak.unsafe_get();
+    sp<IBinder> ret = mRootObjectWeak.promote();
+    ALOGW_IF(hasWeak && ret == nullptr, "RpcServer root object is freed, returning nullptr");
+    return ret;
 }
 
 void RpcServer::join() {
+    while (true) {
+        (void)acceptOne();
+    }
+}
+
+bool RpcServer::acceptOne() {
     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    LOG_ALWAYS_FATAL_IF(!hasServer(), "RpcServer must be setup to join.");
+
+    unique_fd clientFd(
+            TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+
+    if (clientFd < 0) {
+        ALOGE("Could not accept4 socket: %s", strerror(errno));
+        return false;
+    }
+    LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
     {
         std::lock_guard<std::mutex> _l(mLock);
-        LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join.");
+        std::thread thread =
+                std::thread(&RpcServer::establishConnection, this,
+                            std::move(sp<RpcServer>::fromExisting(this)), std::move(clientFd));
+        mConnectingThreads[thread.get_id()] = std::move(thread);
     }
 
-    while (true) {
-        unique_fd clientFd(TEMP_FAILURE_RETRY(
-                accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
-
-        if (clientFd < 0) {
-            ALOGE("Could not accept4 socket: %s", strerror(errno));
-            continue;
-        }
-        LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
-
-        // TODO(b/183988761): cannot trust this simple ID, should not block this
-        // thread
-        LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
-        int32_t id;
-        if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
-            ALOGE("Could not read ID from fd %d", clientFd.get());
-            continue;
-        }
-
-        {
-            std::lock_guard<std::mutex> _l(mLock);
-
-            sp<RpcSession> session;
-            if (id == RPC_SESSION_ID_NEW) {
-                // new client!
-                LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
-                mSessionIdCounter++;
-
-                session = RpcSession::make();
-                session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
-
-                mSessions[mSessionIdCounter] = session;
-            } else {
-                auto it = mSessions.find(id);
-                if (it == mSessions.end()) {
-                    ALOGE("Cannot add thread, no record of session with ID %d", id);
-                    continue;
-                }
-                session = it->second;
-            }
-
-            session->startThread(std::move(clientFd));
-        }
-    }
+    return true;
 }
 
 std::vector<sp<RpcSession>> RpcServer::listSessions() {
@@ -178,14 +166,74 @@
     return sessions;
 }
 
-bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
-    LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
+size_t RpcServer::numUninitializedSessions() {
+    std::lock_guard<std::mutex> _l(mLock);
+    return mConnectingThreads.size();
+}
 
+void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) {
+    LOG_ALWAYS_FATAL_IF(this != server.get(), "Must pass same ownership object");
+
+    // TODO(b/183988761): cannot trust this simple ID
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    bool idValid = true;
+    int32_t id;
+    if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
+        ALOGE("Could not read ID from fd %d", clientFd.get());
+        idValid = false;
+    }
+
+    std::thread thisThread;
+    sp<RpcSession> session;
     {
         std::lock_guard<std::mutex> _l(mLock);
-        LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcServer can only have one server.");
+
+        auto threadId = mConnectingThreads.find(std::this_thread::get_id());
+        LOG_ALWAYS_FATAL_IF(threadId == mConnectingThreads.end(),
+                            "Must establish connection on owned thread");
+        thisThread = std::move(threadId->second);
+        ScopeGuard detachGuard = [&]() { thisThread.detach(); };
+        mConnectingThreads.erase(threadId);
+
+        if (!idValid) {
+            return;
+        }
+
+        if (id == RPC_SESSION_ID_NEW) {
+            LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
+            mSessionIdCounter++;
+
+            session = RpcSession::make();
+            session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
+
+            mSessions[mSessionIdCounter] = session;
+        } else {
+            auto it = mSessions.find(id);
+            if (it == mSessions.end()) {
+                ALOGE("Cannot add thread, no record of session with ID %d", id);
+                return;
+            }
+            session = it->second;
+        }
+
+        detachGuard.Disable();
+        session->preJoin(std::move(thisThread));
     }
 
+    // avoid strong cycle
+    server = nullptr;
+    //
+    //
+    // DO NOT ACCESS MEMBER VARIABLES BELOW
+    //
+
+    session->join(std::move(clientFd));
+}
+
+bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
+    LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
+    LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
+
     unique_fd serverFd(
             TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
     if (serverFd == -1) {
@@ -223,4 +271,27 @@
     (void)mSessions.erase(it);
 }
 
+bool RpcServer::hasServer() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    return mServer.ok();
+}
+
+unique_fd RpcServer::releaseServer() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    return std::move(mServer);
+}
+
+bool RpcServer::setupExternalServer(base::unique_fd serverFd) {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::lock_guard<std::mutex> _l(mLock);
+    if (mServer.ok()) {
+        ALOGE("Each RpcServer can only have one server.");
+        return false;
+    }
+    mServer = std::move(serverFd);
+    return true;
+}
+
 } // namespace android
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index f38135b..05fa49e 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -131,21 +131,13 @@
     return OK;
 }
 
-void RpcSession::startThread(unique_fd client) {
-    std::lock_guard<std::mutex> _l(mMutex);
-    sp<RpcSession> holdThis = sp<RpcSession>::fromExisting(this);
-    int fd = client.release();
-    auto thread = std::thread([=] {
-        holdThis->join(unique_fd(fd));
-        {
-            std::lock_guard<std::mutex> _l(holdThis->mMutex);
-            auto it = mThreads.find(std::this_thread::get_id());
-            LOG_ALWAYS_FATAL_IF(it == mThreads.end());
-            it->second.detach();
-            mThreads.erase(it);
-        }
-    });
-    mThreads[thread.get_id()] = std::move(thread);
+void RpcSession::preJoin(std::thread thread) {
+    LOG_ALWAYS_FATAL_IF(thread.get_id() != std::this_thread::get_id(), "Must own this thread");
+
+    {
+        std::lock_guard<std::mutex> _l(mMutex);
+        mThreads[thread.get_id()] = std::move(thread);
+    }
 }
 
 void RpcSession::join(unique_fd client) {
@@ -165,6 +157,14 @@
 
     LOG_ALWAYS_FATAL_IF(!removeServerConnection(connection),
                         "bad state: connection object guaranteed to be in list");
+
+    {
+        std::lock_guard<std::mutex> _l(mMutex);
+        auto it = mThreads.find(std::this_thread::get_id());
+        LOG_ALWAYS_FATAL_IF(it == mThreads.end());
+        it->second.detach();
+        mThreads.erase(it);
+    }
 }
 
 void RpcSession::terminateLocked() {
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 20fdbfe..e5a6026 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -18,7 +18,9 @@
 
 #include "RpcState.h"
 
+#include <android-base/scopeguard.h>
 #include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/RpcServer.h>
 
 #include "Debug.h"
@@ -28,6 +30,8 @@
 
 namespace android {
 
+using base::ScopeGuard;
+
 RpcState::RpcState() {}
 RpcState::~RpcState() {}
 
@@ -182,6 +186,27 @@
     }
 }
 
+RpcState::CommandData::CommandData(size_t size) : mSize(size) {
+    // The maximum size for regular binder is 1MB for all concurrent
+    // transactions. A very small proportion of transactions are even
+    // larger than a page, but we need to avoid allocating too much
+    // data on behalf of an arbitrary client, or we could risk being in
+    // a position where a single additional allocation could run out of
+    // memory.
+    //
+    // Note, this limit may not reflect the total amount of data allocated for a
+    // transaction (in some cases, additional fixed size amounts are added),
+    // though for rough consistency, we should avoid cases where this data type
+    // is used for multiple dynamic allocations for a single transaction.
+    constexpr size_t kMaxTransactionAllocation = 100 * 1000;
+    if (size == 0) return;
+    if (size > kMaxTransactionAllocation) {
+        ALOGW("Transaction requested too much data allocation %zu", size);
+        return;
+    }
+    mData.reset(new (std::nothrow) uint8_t[size]);
+}
+
 bool RpcState::rpcSend(const base::unique_fd& fd, const char* what, const void* data, size_t size) {
     LOG_RPC_DETAIL("Sending %s on fd %d: %s", what, fd.get(), hexString(data, size).c_str());
 
@@ -326,7 +351,7 @@
             .asyncNumber = asyncNumber,
     };
 
-    ByteVec transactionData(sizeof(RpcWireTransaction) + data.dataSize());
+    CommandData transactionData(sizeof(RpcWireTransaction) + data.dataSize());
     if (!transactionData.valid()) {
         return NO_MEMORY;
     }
@@ -383,7 +408,7 @@
         if (status != OK) return status;
     }
 
-    ByteVec data(command.bodySize);
+    CommandData data(command.bodySize);
     if (!data.valid()) {
         return NO_MEMORY;
     }
@@ -449,6 +474,18 @@
 
 status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
                                         const RpcWireHeader& command) {
+    IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull();
+    IPCThreadState::SpGuard spGuard{"processing binder RPC command"};
+    IPCThreadState::SpGuard* origGuard;
+    if (kernelBinderState != nullptr) {
+        origGuard = kernelBinderState->pushGetCallingSpGuard(&spGuard);
+    }
+    ScopeGuard guardUnguard = [&]() {
+        if (kernelBinderState != nullptr) {
+            kernelBinderState->restoreGetCallingSpGuard(origGuard);
+        }
+    };
+
     switch (command.command) {
         case RPC_COMMAND_TRANSACT:
             return processTransact(fd, session, command);
@@ -469,7 +506,7 @@
                                    const RpcWireHeader& command) {
     LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_TRANSACT, "command: %d", command.command);
 
-    ByteVec transactionData(command.bodySize);
+    CommandData transactionData(command.bodySize);
     if (!transactionData.valid()) {
         return NO_MEMORY;
     }
@@ -490,7 +527,7 @@
 }
 
 status_t RpcState::processTransactInternal(const base::unique_fd& fd, const sp<RpcSession>& session,
-                                           ByteVec transactionData) {
+                                           CommandData transactionData) {
     if (transactionData.size() < sizeof(RpcWireTransaction)) {
         ALOGE("Expecting %zu but got %zu bytes for RpcWireTransaction. Terminating!",
               sizeof(RpcWireTransaction), transactionData.size());
@@ -640,7 +677,7 @@
                 // justification for const_cast (consider avoiding priority_queue):
                 // - AsyncTodo operator< doesn't depend on 'data' object
                 // - gotta go fast
-                ByteVec data = std::move(
+                CommandData data = std::move(
                         const_cast<BinderNode::AsyncTodo&>(it->second.asyncTodo.top()).data);
                 it->second.asyncTodo.pop();
                 _l.unlock();
@@ -654,7 +691,7 @@
             .status = replyStatus,
     };
 
-    ByteVec replyData(sizeof(RpcWireReply) + reply.dataSize());
+    CommandData replyData(sizeof(RpcWireReply) + reply.dataSize());
     if (!replyData.valid()) {
         return NO_MEMORY;
     }
@@ -684,7 +721,7 @@
 status_t RpcState::processDecStrong(const base::unique_fd& fd, const RpcWireHeader& command) {
     LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_DEC_STRONG, "command: %d", command.command);
 
-    ByteVec commandData(command.bodySize);
+    CommandData commandData(command.bodySize);
     if (!commandData.valid()) {
         return NO_MEMORY;
     }
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 83d0344..31f8a22 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -101,10 +101,10 @@
      */
     void terminate();
 
-    // alternative to std::vector<uint8_t> that doesn't abort on too big of allocations
-    struct ByteVec {
-        explicit ByteVec(size_t size)
-              : mData(size > 0 ? new (std::nothrow) uint8_t[size] : nullptr), mSize(size) {}
+    // Alternative to std::vector<uint8_t> that doesn't abort on allocation failure and caps
+    // large allocations to avoid being requested from allocating too much data.
+    struct CommandData {
+        explicit CommandData(size_t size);
         bool valid() { return mSize == 0 || mData != nullptr; }
         size_t size() { return mSize; }
         uint8_t* data() { return mData.get(); }
@@ -128,7 +128,7 @@
                                            const RpcWireHeader& command);
     [[nodiscard]] status_t processTransactInternal(const base::unique_fd& fd,
                                                    const sp<RpcSession>& session,
-                                                   ByteVec transactionData);
+                                                   CommandData transactionData);
     [[nodiscard]] status_t processDecStrong(const base::unique_fd& fd,
                                             const RpcWireHeader& command);
 
@@ -163,7 +163,7 @@
 
         // async transaction queue, _only_ for local binder
         struct AsyncTodo {
-            ByteVec data;
+            CommandData data;
             uint64_t asyncNumber = 0;
 
             bool operator<(const AsyncTodo& o) const {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 23a0cb0..5220b62 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -81,6 +81,32 @@
              */
             uid_t               getCallingUid() const;
 
+            /**
+             * Make it an abort to rely on getCalling* for a section of
+             * execution.
+             *
+             * Usage:
+             *     IPCThreadState::SpGuard guard { "..." };
+             *     auto* orig = pushGetCallingSpGuard(&guard);
+             *     {
+             *         // will abort if you call getCalling*, unless you are
+             *         // serving a nested binder transaction
+             *     }
+             *     restoreCallingSpGuard(orig);
+             */
+            struct SpGuard {
+                const char* context;
+            };
+            SpGuard* pushGetCallingSpGuard(SpGuard* guard);
+            void restoreGetCallingSpGuard(SpGuard* guard);
+            /**
+             * Used internally by getCalling*. Can also be used to assert that
+             * you are in a binder context (getCalling* is valid). This is
+             * intentionally not exposed as a boolean API since code should be
+             * written to know its environment.
+             */
+            void checkContextIsBinderForUse(const char* use) const;
+
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
 
@@ -203,6 +229,7 @@
             Parcel              mOut;
             status_t            mLastError;
             const void*         mServingStackPointer;
+            SpGuard* mServingStackPointerGuard;
             pid_t               mCallingPid;
             const char*         mCallingSid;
             uid_t               mCallingUid;
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index 9659732..f3ba830 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -50,8 +50,12 @@
                               int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
      /**
       * Force the service to persist, even when it has 0 clients.
-      * If setting this flag from the server side, make sure to do so before calling registerService,
-      * or there may be a race with the default dynamic shutdown.
+      * If setting this flag from the server side, make sure to do so before calling
+      * registerService, or there may be a race with the default dynamic shutdown.
+      *
+      * This should only be used if it is every eventually set to false. If a
+      * service needs to persist but doesn't need to dynamically shut down,
+      * prefer to control it with another mechanism such as ctl.start.
       */
      void forcePersist(bool persist);
 
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 3534d51..8f0c6fd 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -22,6 +22,7 @@
 #include <utils/RefBase.h>
 
 #include <mutex>
+#include <thread>
 
 // WARNING: This is a feature which is still in development, and it is subject
 // to radical change. Any production use of this may subject your code to any
@@ -73,6 +74,22 @@
      */
     [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
 
+    /**
+     * If setup*Server has been successful, return true. Otherwise return false.
+     */
+    [[nodiscard]] bool hasServer();
+
+    /**
+     * If hasServer(), return the server FD. Otherwise return invalid FD.
+     */
+    [[nodiscard]] base::unique_fd releaseServer();
+
+    /**
+     * Set up server using an external FD previously set up by releaseServer().
+     * Return false if there's already a server.
+     */
+    bool setupExternalServer(base::unique_fd serverFd);
+
     void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
 
     /**
@@ -89,8 +106,14 @@
     /**
      * The root object can be retrieved by any client, without any
      * authentication. TODO(b/183988761)
+     *
+     * Holds a strong reference to the root object.
      */
     void setRootObject(const sp<IBinder>& binder);
+    /**
+     * Holds a weak reference to the root object.
+     */
+    void setRootObjectWeak(const wp<IBinder>& binder);
     sp<IBinder> getRootObject();
 
     /**
@@ -101,9 +124,16 @@
     void join();
 
     /**
+     * Accept one connection on this server. You must have at least one client
+     * session before calling this.
+     */
+    [[nodiscard]] bool acceptOne();
+
+    /**
      * For debugging!
      */
     std::vector<sp<RpcSession>> listSessions();
+    size_t numUninitializedSessions();
 
     ~RpcServer();
 
@@ -115,6 +145,7 @@
     friend sp<RpcServer>;
     RpcServer();
 
+    void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd);
     bool setupSocketServer(const RpcSocketAddress& address);
 
     bool mAgreedExperimental = false;
@@ -123,7 +154,9 @@
     base::unique_fd mServer; // socket we are accepting sessions on
 
     std::mutex mLock; // for below
+    std::map<std::thread::id, std::thread> mConnectingThreads;
     sp<IBinder> mRootObject;
+    wp<IBinder> mRootObjectWeak;
     std::map<int32_t, sp<RpcSession>> mSessions;
     int32_t mSessionIdCounter = 0;
 };
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index c8ab9e4..bcc213c 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -114,7 +114,9 @@
 
     status_t readId();
 
-    void startThread(base::unique_fd client);
+    // transfer ownership of thread
+    void preJoin(std::thread thread);
+    // join on thread passed to preJoin
     void join(base::unique_fd client);
     void terminateLocked();
 
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index a90b4aa..2a66941 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -35,7 +35,7 @@
  * \return EX_NONE on success.
  */
 __attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService(
-        AIBinder* binder, const char* instance);
+        AIBinder* binder, const char* instance) __INTRODUCED_IN(29);
 
 /**
  * Gets a binder object with this specific instance name. Will return nullptr immediately if the
@@ -47,7 +47,8 @@
  *
  * \param instance identifier of the service used to lookup the service.
  */
-__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance);
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance)
+        __INTRODUCED_IN(29);
 
 /**
  * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
@@ -59,7 +60,8 @@
  *
  * \param instance identifier of the service used to lookup the service.
  */
-__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance)
+        __INTRODUCED_IN(29);
 
 /**
  * Registers a lazy service with the default service manager under the 'instance' name.
@@ -135,6 +137,10 @@
 /**
  * Prevent lazy services without client from shutting down their process
  *
+ * This should only be used if it is every eventually set to false. If a
+ * service needs to persist but doesn't need to dynamically shut down,
+ * prefer to control it with another mechanism.
+ *
  * \param persist 'true' if the process should not exit.
  */
 void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index ef4198d..41daccc 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -55,4 +55,6 @@
     oneway void sleepMsAsync(int ms);
 
     void die(boolean cleanup);
+
+    void useKernelBinderCallingId();
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 0c3fbcd..45b2776 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -73,6 +73,7 @@
     BINDER_LIB_TEST_REGISTER_SERVER,
     BINDER_LIB_TEST_ADD_SERVER,
     BINDER_LIB_TEST_ADD_POLL_SERVER,
+    BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION,
     BINDER_LIB_TEST_CALL_BACK,
     BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF,
     BINDER_LIB_TEST_DELAYED_CALL_BACK,
@@ -604,6 +605,24 @@
     EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
 }
 
+TEST_F(BinderLibTest, NoBinderCallContextGuard) {
+    IPCThreadState::SpGuard spGuard{"NoBinderCallContext"};
+    IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
+    // yes, this test uses threads, but it's careful and uses fork in addServer
+    EXPECT_DEATH({ IPCThreadState::self()->getCallingPid(); },
+                 "In context NoBinderCallContext, getCallingPid does not make sense.");
+
+    IPCThreadState::self()->restoreGetCallingSpGuard(origGuard);
+}
+
+TEST_F(BinderLibTest, BinderCallContextGuard) {
+    sp<IBinder> binder = addServer();
+    Parcel data, reply;
+    EXPECT_THAT(binder->transact(BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, data, &reply),
+                StatusEq(DEAD_OBJECT));
+}
+
 TEST_F(BinderLibTest, AddServer)
 {
     sp<IBinder> server = addServer();
@@ -1262,6 +1281,18 @@
                 pthread_mutex_unlock(&m_serverWaitMutex);
                 return ret;
             }
+            case BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION: {
+                IPCThreadState::SpGuard spGuard{"GuardInBinderTransaction"};
+                IPCThreadState::SpGuard *origGuard =
+                        IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
+                // if the guard works, this should abort
+                (void)IPCThreadState::self()->getCallingPid();
+
+                IPCThreadState::self()->restoreGetCallingSpGuard(origGuard);
+                return NO_ERROR;
+            }
+
             case BINDER_LIB_TEST_GETPID:
                 reply->writeInt32(getpid());
                 return NO_ERROR;
@@ -1489,6 +1520,11 @@
 {
     binderLibTestServiceName += String16(binderserversuffix);
 
+    // Testing to make sure that calls that we are serving can use getCallin*
+    // even though we don't here.
+    IPCThreadState::SpGuard spGuard{"main server thread"};
+    (void)IPCThreadState::self()->pushGetCallingSpGuard(&spGuard);
+
     status_t ret;
     sp<IServiceManager> sm = defaultServiceManager();
     BinderLibTestService* testServicePtr;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index b3ce744..3f94df2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -23,6 +23,7 @@
 #include <android/binder_libbinder.h>
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <binder/RpcServer.h>
@@ -49,6 +50,19 @@
     EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "");
 }
 
+TEST(BinderRpc, SetExternalServer) {
+    base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
+    int sinkFd = sink.get();
+    auto server = RpcServer::make();
+    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+    ASSERT_FALSE(server->hasServer());
+    ASSERT_TRUE(server->setupExternalServer(std::move(sink)));
+    ASSERT_TRUE(server->hasServer());
+    base::unique_fd retrieved = server->releaseServer();
+    ASSERT_FALSE(server->hasServer());
+    ASSERT_EQ(sinkFd, retrieved.get());
+}
+
 using android::binder::Status;
 
 #define EXPECT_OK(status)                 \
@@ -178,6 +192,13 @@
             _exit(1);
         }
     }
+    Status useKernelBinderCallingId() override {
+        // this is WRONG! It does not make sense when using RPC binder, and
+        // because it is SO wrong, and so much code calls this, it should abort!
+
+        (void)IPCThreadState::self()->getCallingPid();
+        return Status::ok();
+    }
 };
 sp<IBinder> MyBinderRpcTest::mHeldBinder;
 
@@ -874,6 +895,19 @@
     }
 }
 
+TEST_P(BinderRpc, UseKernelBinderCallingId) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    // we can't allocate IPCThreadState so actually the first time should
+    // succeed :(
+    EXPECT_OK(proc.rootIface->useKernelBinderCallingId());
+
+    // second time! we catch the error :)
+    EXPECT_EQ(DEAD_OBJECT, proc.rootIface->useKernelBinderCallingId().transactionError());
+
+    proc.expectInvalid = true;
+}
+
 TEST_P(BinderRpc, WorksWithLibbinderNdkPing) {
     auto proc = createRpcTestSocketServerProcess(1);
 
@@ -929,6 +963,34 @@
                         }),
                         PrintSocketType);
 
+class BinderRpcServerRootObject : public ::testing::TestWithParam<std::tuple<bool, bool>> {};
+
+TEST_P(BinderRpcServerRootObject, WeakRootObject) {
+    using SetFn = std::function<void(RpcServer*, sp<IBinder>)>;
+    auto setRootObject = [](bool isStrong) -> SetFn {
+        return isStrong ? SetFn(&RpcServer::setRootObject) : SetFn(&RpcServer::setRootObjectWeak);
+    };
+
+    auto server = RpcServer::make();
+    auto [isStrong1, isStrong2] = GetParam();
+    auto binder1 = sp<BBinder>::make();
+    IBinder* binderRaw1 = binder1.get();
+    setRootObject(isStrong1)(server.get(), binder1);
+    EXPECT_EQ(binderRaw1, server->getRootObject());
+    binder1.clear();
+    EXPECT_EQ((isStrong1 ? binderRaw1 : nullptr), server->getRootObject());
+
+    auto binder2 = sp<BBinder>::make();
+    IBinder* binderRaw2 = binder2.get();
+    setRootObject(isStrong2)(server.get(), binder2);
+    EXPECT_EQ(binderRaw2, server->getRootObject());
+    binder2.clear();
+    EXPECT_EQ((isStrong2 ? binderRaw2 : nullptr), server->getRootObject());
+}
+
+INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerRootObject,
+                        ::testing::Combine(::testing::Bool(), ::testing::Bool()));
+
 } // namespace android
 
 int main(int argc, char** argv) {
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
new file mode 100644
index 0000000..1c75306
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -0,0 +1,40 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_fuzz {
+    name: "binder_rpc_fuzzer",
+    host_supported: true,
+
+    fuzz_config: {
+        cc: ["smoreland@google.com"],
+    },
+
+    srcs: [
+        "main.cpp",
+    ],
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+
+    target: {
+        android: {
+            shared_libs: [
+                "libbinder",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libbinder",
+            ],
+        },
+    },
+}
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
new file mode 100644
index 0000000..3603ebe
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <binder/Binder.h>
+#include <binder/Parcel.h>
+#include <binder/RpcServer.h>
+#include <binder/RpcSession.h>
+
+#include <sys/resource.h>
+#include <sys/un.h>
+
+namespace android {
+
+static const std::string kSock = std::string(getenv("TMPDIR") ?: "/tmp") +
+        "/binderRpcFuzzerSocket_" + std::to_string(getpid());
+
+size_t getHardMemoryLimit() {
+    struct rlimit limit;
+    CHECK(0 == getrlimit(RLIMIT_AS, &limit)) << errno;
+    return limit.rlim_max;
+}
+
+void setMemoryLimit(size_t cur, size_t max) {
+    const struct rlimit kLimit = {
+            .rlim_cur = cur,
+            .rlim_max = max,
+    };
+    CHECK(0 == setrlimit(RLIMIT_AS, &kLimit)) << errno;
+}
+
+class SomeBinder : public BBinder {
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {
+        (void)flags;
+
+        if ((code & 1) == 0) {
+            sp<IBinder> binder;
+            (void)data.readStrongBinder(&binder);
+            if (binder != nullptr) {
+                (void)binder->pingBinder();
+            }
+        }
+        if ((code & 2) == 0) {
+            (void)data.readInt32();
+        }
+        if ((code & 4) == 0) {
+            (void)reply->writeStrongBinder(sp<BBinder>::make());
+        }
+
+        return OK;
+    }
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size > 50000) return 0;
+
+    unlink(kSock.c_str());
+
+    sp<RpcServer> server = RpcServer::make();
+    server->setRootObject(sp<SomeBinder>::make());
+    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+    CHECK(server->setupUnixDomainServer(kSock.c_str()));
+
+    static constexpr size_t kMemLimit = 1llu * 1024 * 1024 * 1024;
+    size_t hardLimit = getHardMemoryLimit();
+    setMemoryLimit(std::min(kMemLimit, hardLimit), hardLimit);
+
+    std::thread serverThread([=] { (void)server->acceptOne(); });
+
+    sockaddr_un addr{
+            .sun_family = AF_UNIX,
+    };
+    CHECK_LT(kSock.size(), sizeof(addr.sun_path));
+    memcpy(&addr.sun_path, kSock.c_str(), kSock.size());
+
+    base::unique_fd clientFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+    CHECK_NE(clientFd.get(), -1);
+    CHECK_EQ(0,
+             TEMP_FAILURE_RETRY(
+                     connect(clientFd.get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))))
+            << strerror(errno);
+
+    serverThread.join();
+
+    // TODO(b/182938024): fuzz multiple sessions, instead of just one
+
+#if 0
+    // make fuzzer more productive locally by forcing it to create a new session
+    int32_t id = -1;
+    CHECK(base::WriteFully(clientFd, &id, sizeof(id)));
+#endif
+
+    CHECK(base::WriteFully(clientFd, data, size));
+
+    clientFd.reset();
+
+    // TODO(b/185167543): better way to force a server to shutdown
+    while (!server->listSessions().empty() && server->numUninitializedSessions()) {
+        usleep(1);
+    }
+
+    setMemoryLimit(hardLimit, hardLimit);
+
+    return 0;
+}
+
+} // namespace android