Merge "clang-format ProcessState."
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/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 95c4923..c9a7c7b 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1695,6 +1695,12 @@
 
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
 
+    // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
+    // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
+    // dump with priority parameters to dump high priority information.
+    RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
+                   CommandOptions::WithTimeout(10).Build());
+
     RunCommand("SYSTEM PROPERTIES", {"getprop"});
 
     RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
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/Android.bp b/libs/binder/Android.bp
index 31227ab..f157aa2 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -64,6 +64,9 @@
     "PermissionCache.cpp",
     "PermissionController.cpp",
 ]
+libbinder_no_vendor_interface_sources = [
+    ":packagemanager_aidl",
+]
 
 cc_library {
     name: "libbinder",
@@ -123,9 +126,8 @@
         "Status.cpp",
         "TextOutput.cpp",
         "Utils.cpp",
-        ":packagemanager_aidl",
         ":libbinder_aidl",
-    ],
+    ] + libbinder_no_vendor_interface_sources,
 
     target: {
         android: {
@@ -137,7 +139,7 @@
             },
         },
         vendor: {
-            exclude_srcs: libbinder_device_interface_sources,
+            exclude_srcs: libbinder_device_interface_sources + libbinder_no_vendor_interface_sources,
         },
         darwin: {
             enabled: false,
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index ef7fd44..d2919e7 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -366,19 +366,46 @@
 
 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;
 }
 
+const IPCThreadState::SpGuard* IPCThreadState::pushGetCallingSpGuard(const SpGuard* guard) {
+    const SpGuard* orig = mServingStackPointerGuard;
+    mServingStackPointerGuard = guard;
+    return orig;
+}
+
+void IPCThreadState::restoreGetCallingSpGuard(const SpGuard* guard) {
+    mServingStackPointerGuard = guard;
+}
+
+void IPCThreadState::checkContextIsBinderForUse(const char* use) const {
+    if (LIKELY(mServingStackPointerGuard == nullptr)) return;
+
+    if (!mServingStackPointer || mServingStackPointerGuard->address < mServingStackPointer) {
+        LOG_ALWAYS_FATAL("In context %s, %s does not make sense (binder sp: %p, guard: %p).",
+                         mServingStackPointerGuard->context, use, mServingStackPointer,
+                         mServingStackPointerGuard->address);
+    }
+
+    // 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 +874,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);
@@ -1230,7 +1257,7 @@
                 tr.offsets_size/sizeof(binder_size_t), freeBuffer);
 
             const void* origServingStackPointer = mServingStackPointer;
-            mServingStackPointer = &origServingStackPointer; // anything on the stack
+            mServingStackPointer = __builtin_frame_address(0);
 
             const pid_t origPid = mCallingPid;
             const char* origSid = mCallingSid;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e4dfa52..9795348 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1466,6 +1466,29 @@
     return nullptr;
 }
 
+status_t Parcel::readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const {
+    if (status_t status = readInt32(size); status != OK) return status;
+    if (*size < 0) return OK; // may be null, client to handle
+
+    LOG_ALWAYS_FATAL_IF(elmSize > INT32_MAX, "Cannot have element as big as %zu", elmSize);
+
+    // approximation, can't know max element size (e.g. if it makes heap
+    // allocations)
+    static_assert(sizeof(int) == sizeof(int32_t), "Android is LP64");
+    int32_t allocationSize;
+    if (__builtin_smul_overflow(elmSize, *size, &allocationSize)) return NO_MEMORY;
+
+    // High limit of 1MB since something this big could never be returned. Could
+    // probably scope this down, but might impact very specific usecases.
+    constexpr int32_t kMaxAllocationSize = 1 * 1000 * 1000;
+
+    if (allocationSize >= kMaxAllocationSize) {
+        return NO_MEMORY;
+    }
+
+    return OK;
+}
+
 template<class T>
 status_t Parcel::readAligned(T *pArg) const {
     static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index dc10d1c..e31aea0 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -16,19 +16,21 @@
 
 #define LOG_TAG "RpcServer"
 
+#include <poll.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
 #include <thread>
 #include <vector>
 
+#include <android-base/macros.h>
 #include <android-base/scopeguard.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
 #include <log/log.h>
-#include "RpcState.h"
 
 #include "RpcSocketAddress.h"
+#include "RpcState.h"
 #include "RpcWireFormat.h"
 
 namespace android {
@@ -99,7 +101,7 @@
 
 void RpcServer::setMaxThreads(size_t threads) {
     LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads");
-    LOG_ALWAYS_FATAL_IF(mStarted, "must be called before started");
+    LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running");
     mMaxThreads = threads;
 }
 
@@ -126,16 +128,61 @@
     return ret;
 }
 
+std::unique_ptr<RpcServer::FdTrigger> RpcServer::FdTrigger::make() {
+    auto ret = std::make_unique<RpcServer::FdTrigger>();
+    if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) return nullptr;
+    return ret;
+}
+
+void RpcServer::FdTrigger::trigger() {
+    mWrite.reset();
+}
+
 void RpcServer::join() {
-    while (true) {
-        (void)acceptOne();
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
+        LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
+        mJoinThreadRunning = true;
+        mShutdownTrigger = FdTrigger::make();
+        LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler");
     }
+
+    while (true) {
+        pollfd pfd[]{{.fd = mServer.get(), .events = POLLIN, .revents = 0},
+                     {.fd = mShutdownTrigger->readFd().get(), .events = POLLHUP, .revents = 0}};
+        int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
+        if (ret < 0) {
+            ALOGE("Could not poll socket: %s", strerror(errno));
+            continue;
+        }
+        if (ret == 0) {
+            continue;
+        }
+        if (pfd[1].revents & POLLHUP) {
+            LOG_RPC_DETAIL("join() exiting because shutdown requested.");
+            break;
+        }
+
+        (void)acceptOneNoCheck();
+    }
+
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        mJoinThreadRunning = false;
+    }
+    mShutdownCv.notify_all();
 }
 
 bool RpcServer::acceptOne() {
     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
-    LOG_ALWAYS_FATAL_IF(!hasServer(), "RpcServer must be setup to join.");
+    LOG_ALWAYS_FATAL_IF(!hasServer(), "RpcServer must be setup to acceptOne.");
+    return acceptOneNoCheck();
+}
 
+bool RpcServer::acceptOneNoCheck() {
     unique_fd clientFd(
             TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
 
@@ -156,6 +203,18 @@
     return true;
 }
 
+bool RpcServer::shutdown() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    std::unique_lock<std::mutex> _l(mLock);
+    if (mShutdownTrigger == nullptr) return false;
+
+    mShutdownTrigger->trigger();
+    while (mJoinThreadRunning) mShutdownCv.wait(_l);
+
+    mShutdownTrigger = nullptr;
+    return true;
+}
+
 std::vector<sp<RpcSession>> RpcServer::listSessions() {
     std::lock_guard<std::mutex> _l(mLock);
     std::vector<sp<RpcSession>> sessions;
@@ -255,7 +314,10 @@
 
     LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str());
 
-    mServer = std::move(serverFd);
+    if (!setupExternalServer(std::move(serverFd))) {
+        ALOGE("Another thread has set up server while calling setupSocketServer. Race?");
+        return false;
+    }
     return true;
 }
 
@@ -272,8 +334,26 @@
 }
 
 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/RpcState.cpp b/libs/binder/RpcState.cpp
index 2ba9fa2..230de6f 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() {}
 
@@ -470,6 +474,21 @@
 
 status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
                                         const RpcWireHeader& command) {
+    IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull();
+    IPCThreadState::SpGuard spGuard{
+            .address = __builtin_frame_address(0),
+            .context = "processing binder RPC command",
+    };
+    const 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);
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 23a0cb0..ee661a5 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -81,6 +81,36 @@
              */
             uid_t               getCallingUid() const;
 
+            /**
+             * Make it an abort to rely on getCalling* for a section of
+             * execution.
+             *
+             * Usage:
+             *     IPCThreadState::SpGuard guard {
+             *        .address = __builtin_frame_address(0),
+             *        .context = "...",
+             *     };
+             *     const auto* orig = pushGetCallingSpGuard(&guard);
+             *     {
+             *         // will abort if you call getCalling*, unless you are
+             *         // serving a nested binder transaction
+             *     }
+             *     restoreCallingSpGuard(orig);
+             */
+            struct SpGuard {
+                const void* address;
+                const char* context;
+            };
+            const SpGuard* pushGetCallingSpGuard(const SpGuard* guard);
+            void restoreGetCallingSpGuard(const 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 +233,7 @@
             Parcel              mOut;
             status_t            mLastError;
             const void*         mServingStackPointer;
+            const 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/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5aaaa0c..02052ad 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -561,6 +561,8 @@
     status_t            flattenBinder(const sp<IBinder>& binder);
     status_t            unflattenBinder(sp<IBinder>* out) const;
 
+    status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const;
+
     template<class T>
     status_t            readAligned(T *pArg) const;
 
@@ -1315,7 +1317,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::vector<T>* val) const {
     int32_t size;
-    status_t err = readInt32(&size);
+    status_t err = readOutVectorSizeWithCheck(sizeof(T), &size);
     if (err != NO_ERROR) {
         return err;
     }
@@ -1330,7 +1332,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const {
     int32_t size;
-    status_t err = readInt32(&size);
+    status_t err = readOutVectorSizeWithCheck(sizeof(T), &size);
     if (err != NO_ERROR) {
         return err;
     }
@@ -1346,7 +1348,7 @@
 template<typename T>
 status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
     int32_t size;
-    status_t err = readInt32(&size);
+    status_t err = readOutVectorSizeWithCheck(sizeof(T), &size);
     if (err != NO_ERROR) {
         return err;
     }
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 771bbe6..4973400 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -79,6 +79,17 @@
      */
     [[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();
 
     /**
@@ -108,11 +119,22 @@
     /**
      * You must have at least one client session before calling this.
      *
-     * TODO(b/185167543): way to shut down?
+     * If a client needs to actively terminate join, call shutdown() in a separate thread.
+     *
+     * At any given point, there can only be one thread calling join().
      */
     void join();
 
     /**
+     * Shut down any existing join(). Return true if successfully shut down, false otherwise
+     * (e.g. no join() is running). Will wait for the server to be fully
+     * shutdown.
+     *
+     * TODO(b/185167543): wait for sessions to shutdown as well
+     */
+    [[nodiscard]] bool shutdown();
+
+    /**
      * Accept one connection on this server. You must have at least one client
      * session before calling this.
      */
@@ -131,14 +153,31 @@
     void onSessionTerminating(const sp<RpcSession>& session);
 
 private:
+    /** This is not a pipe. */
+    struct FdTrigger {
+        static std::unique_ptr<FdTrigger> make();
+        /**
+         * poll() on this fd for POLLHUP to get notification when trigger is called
+         */
+        base::borrowed_fd readFd() const { return mRead; }
+        /**
+         * Close the write end of the pipe so that the read end receives POLLHUP.
+         */
+        void trigger();
+
+    private:
+        base::unique_fd mWrite;
+        base::unique_fd mRead;
+    };
+
     friend sp<RpcServer>;
     RpcServer();
 
     void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd);
     bool setupSocketServer(const RpcSocketAddress& address);
+    [[nodiscard]] bool acceptOneNoCheck();
 
     bool mAgreedExperimental = false;
-    bool mStarted = false; // TODO(b/185167543): support dynamically added clients
     size_t mMaxThreads = 1;
     base::unique_fd mServer; // socket we are accepting sessions on
 
@@ -148,6 +187,9 @@
     wp<IBinder> mRootObjectWeak;
     std::map<int32_t, sp<RpcSession>> mSessions;
     int32_t mSessionIdCounter = 0;
+    bool mJoinThreadRunning = false;
+    std::unique_ptr<FdTrigger> mShutdownTrigger;
+    std::condition_variable mShutdownCv;
 };
 
 } // namespace android
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 83190aa..5092d87 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -910,6 +910,9 @@
     if (err != STATUS_OK) return err;
     if (size < 0) return STATUS_UNEXPECTED_NULL;
 
+    // TODO(b/188215728): delegate to libbinder_ndk
+    if (size > 1000000) return STATUS_NO_MEMORY;
+
     vec->resize(static_cast<size_t>(size));
     return STATUS_OK;
 }
@@ -931,6 +934,9 @@
         return STATUS_OK;
     }
 
+    // TODO(b/188215728): delegate to libbinder_ndk
+    if (size > 1000000) return STATUS_NO_MEMORY;
+
     *vec = std::optional<std::vector<T>>(std::vector<T>{});
     (*vec)->resize(static_cast<size_t>(size));
     return STATUS_OK;
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 9e2050b..78f2d3a 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -150,6 +150,11 @@
 /**
  * This is called whenever a transaction needs to be processed by a local implementation.
  *
+ * This method will be called after the equivalent of
+ * android.os.Parcel#enforceInterface is called. That is, the interface
+ * descriptor associated with the AIBinder_Class descriptor will already be
+ * checked.
+ *
  * \param binder the object being transacted on.
  * \param code implementation-specific code representing which transaction should be taken.
  * \param in the implementation-specific input data to this transaction.
@@ -452,12 +457,14 @@
  */
 
 /**
- * Creates a parcel to start filling out for a transaction. This may add data to the parcel for
- * security, debugging, or other purposes. This parcel is to be sent via AIBinder_transact and it
- * represents the input data to the transaction. It is recommended to check if the object is local
- * and call directly into its user data before calling this as the parceling and unparceling cost
- * can be avoided. This AIBinder must be either built with a class or associated with a class before
- * using this API.
+ * Creates a parcel to start filling out for a transaction. This will add a header to the
+ * transaction that corresponds to android.os.Parcel#writeInterfaceToken. This may add debugging
+ * or other information to the transaction for platform use or to enable other features to work. The
+ * contents of this header is a platform implementation detail, and it is required to use
+ * libbinder_ndk. This parcel is to be sent via AIBinder_transact and it represents the input data
+ * to the transaction. It is recommended to check if the object is local and call directly into its
+ * user data before calling this as the parceling and unparceling cost can be avoided. This AIBinder
+ * must be either built with a class or associated with a class before using this API.
  *
  * This does not affect the ownership of binder. When this function succeeds, the in parcel's
  * ownership is passed to the caller. At this point, the parcel can be filled out and passed to
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index c610927..2a66941 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -137,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/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index ec7c7d8..b2f21c7 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -46,7 +46,8 @@
 template <typename T>
 using ArraySetter = void (*)(void* arrayData, size_t index, T value);
 
-binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) {
+static binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray,
+                                                 int32_t length) {
     // only -1 can be used to represent a null array
     if (length < -1) return STATUS_BAD_VALUE;
 
@@ -61,12 +62,24 @@
 
     Parcel* rawParcel = parcel->get();
 
-    status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
+    status_t status = rawParcel->writeInt32(length);
     if (status != STATUS_OK) return PruneStatusT(status);
 
     return STATUS_OK;
 }
 
+static binder_status_t ReadAndValidateArraySize(const AParcel* parcel, int32_t* length) {
+    if (status_t status = parcel->get()->readInt32(length); status != STATUS_OK) {
+        return PruneStatusT(status);
+    }
+
+    if (*length < -1) return STATUS_BAD_VALUE;  // libbinder_ndk reserves these
+    if (*length <= 0) return STATUS_OK;         // null
+    if (static_cast<size_t>(*length) > parcel->get()->dataAvail()) return STATUS_NO_MEMORY;
+
+    return STATUS_OK;
+}
+
 template <typename T>
 binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) {
     binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
@@ -111,10 +124,9 @@
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
-    status_t status = rawParcel->readInt32(&length);
-
-    if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < -1) return STATUS_BAD_VALUE;
+    if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) {
+        return status;
+    }
 
     T* array;
     if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
@@ -140,10 +152,9 @@
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
-    status_t status = rawParcel->readInt32(&length);
-
-    if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < -1) return STATUS_BAD_VALUE;
+    if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) {
+        return status;
+    }
 
     char16_t* array;
     if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
@@ -155,7 +166,7 @@
     if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
 
     for (int32_t i = 0; i < length; i++) {
-        status = rawParcel->readChar(array + i);
+        status_t status = rawParcel->readChar(array + i);
 
         if (status != STATUS_OK) return PruneStatusT(status);
     }
@@ -189,10 +200,9 @@
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
-    status_t status = rawParcel->readInt32(&length);
-
-    if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < -1) return STATUS_BAD_VALUE;
+    if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) {
+        return status;
+    }
 
     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
@@ -200,7 +210,7 @@
 
     for (int32_t i = 0; i < length; i++) {
         T readTarget;
-        status = (rawParcel->*read)(&readTarget);
+        status_t status = (rawParcel->*read)(&readTarget);
         if (status != STATUS_OK) return PruneStatusT(status);
 
         setter(arrayData, i, readTarget);
@@ -402,13 +412,10 @@
 binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
                                         AParcel_stringArrayAllocator allocator,
                                         AParcel_stringArrayElementAllocator elementAllocator) {
-    const Parcel* rawParcel = parcel->get();
-
     int32_t length;
-    status_t status = rawParcel->readInt32(&length);
-
-    if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < -1) return STATUS_BAD_VALUE;
+    if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) {
+        return status;
+    }
 
     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
@@ -449,13 +456,10 @@
 binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData,
                                             AParcel_parcelableArrayAllocator allocator,
                                             AParcel_readParcelableElement elementReader) {
-    const Parcel* rawParcel = parcel->get();
-
     int32_t length;
-    status_t status = rawParcel->readInt32(&length);
-
-    if (status != STATUS_OK) return PruneStatusT(status);
-    if (length < -1) return STATUS_BAD_VALUE;
+    if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) {
+        return status;
+    }
 
     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 49d3401..7d655d8 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -26,6 +26,7 @@
     },
     apex_available: [
         "//apex_available:platform",
+        "com.android.compos",
         "com.android.virt",
     ],
 }
@@ -48,6 +49,7 @@
     },
     apex_available: [
         "//apex_available:platform",
+        "com.android.compos",
         "com.android.virt",
     ],
     lints: "none",
@@ -99,6 +101,7 @@
     },
     apex_available: [
         "//apex_available:platform",
+        "com.android.compos",
         "com.android.virt",
     ],
 }
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 459bb29..963d7b3 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,13 @@
     EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
 }
 
+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();
@@ -1252,6 +1260,21 @@
                 pthread_mutex_unlock(&m_serverWaitMutex);
                 return ret;
             }
+            case BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION: {
+                IPCThreadState::SpGuard spGuard{
+                        .address = __builtin_frame_address(0),
+                        .context = "GuardInBinderTransaction",
+                };
+                const 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;
@@ -1477,6 +1500,14 @@
 {
     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{
+            .address = __builtin_frame_address(0),
+            .context = "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 260be57..e10fe2f 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>
@@ -40,6 +41,8 @@
 #include "../RpcState.h"   // for debugging
 #include "../vm_sockets.h" // for VMADDR_*
 
+using namespace std::chrono_literals;
+
 namespace android {
 
 TEST(BinderRpcParcel, EntireParcelFormatted) {
@@ -49,6 +52,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 +194,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 +897,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);
 
@@ -957,6 +993,54 @@
 INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerRootObject,
                         ::testing::Combine(::testing::Bool(), ::testing::Bool()));
 
+class OneOffSignal {
+public:
+    // If notify() was previously called, or is called within |duration|, return true; else false.
+    template <typename R, typename P>
+    bool wait(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        return mCv.wait_for(lock, duration, [this] { return mValue; });
+    }
+    void notify() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mValue = true;
+        lock.unlock();
+        mCv.notify_all();
+    }
+
+private:
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    bool mValue = false;
+};
+
+TEST(BinderRpc, Shutdown) {
+    auto addr = allocateSocketAddress();
+    unlink(addr.c_str());
+    auto server = RpcServer::make();
+    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+    ASSERT_TRUE(server->setupUnixDomainServer(addr.c_str()));
+    auto joinEnds = std::make_shared<OneOffSignal>();
+
+    // If things are broken and the thread never stops, don't block other tests. Because the thread
+    // may run after the test finishes, it must not access the stack memory of the test. Hence,
+    // shared pointers are passed.
+    std::thread([server, joinEnds] {
+        server->join();
+        joinEnds->notify();
+    }).detach();
+
+    bool shutdown = false;
+    for (int i = 0; i < 10 && !shutdown; i++) {
+        usleep(300 * 1000); // 300ms; total 3s
+        if (server->shutdown()) shutdown = true;
+    }
+    ASSERT_TRUE(shutdown) << "server->shutdown() never returns true";
+
+    ASSERT_TRUE(joinEnds->wait(2s))
+            << "After server->shutdown() returns true, join() did not stop after 2s";
+}
+
 } // namespace android
 
 int main(int argc, char** argv) {
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 394d222..5f2c17c 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -66,6 +66,10 @@
     int32_t mValue = 0;
 };
 
+struct BigStruct {
+    uint8_t data[1337];
+};
+
 #define PARCEL_READ_WITH_STATUS(T, FUN) \
     [] (const ::android::Parcel& p, uint8_t /*data*/) {\
         FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
@@ -158,22 +162,20 @@
     PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
     PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
 
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // PARCEL_READ_WITH_STATUS(std::vector<ByteEnum>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<ByteEnum>>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<ByteEnum>>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<IntEnum>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<IntEnum>>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<IntEnum>>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<LongEnum>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<LongEnum>>, readEnumVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<LongEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::vector<ByteEnum>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<ByteEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<ByteEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::vector<IntEnum>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<IntEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<IntEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::vector<LongEnum>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<LongEnum>>, readEnumVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<LongEnum>>, readEnumVector),
 
     // only reading one parcelable type for now
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<ExampleParcelable>>>, readParcelableVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<ExampleParcelable>, readParcelableVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<ExampleParcelable>>>, readParcelableVector),
+    PARCEL_READ_WITH_STATUS(std::vector<ExampleParcelable>, readParcelableVector),
     PARCEL_READ_WITH_STATUS(ExampleParcelable, readParcelable),
     PARCEL_READ_WITH_STATUS(std::unique_ptr<ExampleParcelable>, readParcelable),
     PARCEL_READ_WITH_STATUS(std::optional<ExampleParcelable>, readParcelable),
@@ -182,45 +184,43 @@
     PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder),
     PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder),
 
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
-    // PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::IBinder>>, readStrongBinderVector),
+    PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
+    PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
+    PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::IBinder>>, readStrongBinderVector),
 
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int8_t>>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int8_t>>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<int8_t>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, readByteVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int32_t>>, readInt32Vector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int32_t>>, readInt32Vector),
-    // PARCEL_READ_WITH_STATUS(std::vector<int32_t>, readInt32Vector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int64_t>>, readInt64Vector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<int64_t>>, readInt64Vector),
-    // PARCEL_READ_WITH_STATUS(std::vector<int64_t>, readInt64Vector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint64_t>>, readUint64Vector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint64_t>>, readUint64Vector),
-    // PARCEL_READ_WITH_STATUS(std::vector<uint64_t>, readUint64Vector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<float>>, readFloatVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<float>>, readFloatVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<float>, readFloatVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<double>>, readDoubleVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<double>>, readDoubleVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<double>, readDoubleVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<bool>>, readBoolVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<bool>>, readBoolVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<bool>, readBoolVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<char16_t>>, readCharVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<char16_t>>, readCharVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<char16_t>, readCharVector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<android::String16>>>, readString16Vector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<android::String16>>>, readString16Vector),
-    // PARCEL_READ_WITH_STATUS(std::vector<android::String16>, readString16Vector),
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<std::string>>>, readUtf8VectorFromUtf16Vector),
-    // PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int8_t>>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<int8_t>>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::vector<int8_t>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, readByteVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int32_t>>, readInt32Vector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<int32_t>>, readInt32Vector),
+    PARCEL_READ_WITH_STATUS(std::vector<int32_t>, readInt32Vector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int64_t>>, readInt64Vector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<int64_t>>, readInt64Vector),
+    PARCEL_READ_WITH_STATUS(std::vector<int64_t>, readInt64Vector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint64_t>>, readUint64Vector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint64_t>>, readUint64Vector),
+    PARCEL_READ_WITH_STATUS(std::vector<uint64_t>, readUint64Vector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<float>>, readFloatVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<float>>, readFloatVector),
+    PARCEL_READ_WITH_STATUS(std::vector<float>, readFloatVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<double>>, readDoubleVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<double>>, readDoubleVector),
+    PARCEL_READ_WITH_STATUS(std::vector<double>, readDoubleVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<bool>>, readBoolVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<bool>>, readBoolVector),
+    PARCEL_READ_WITH_STATUS(std::vector<bool>, readBoolVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<char16_t>>, readCharVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<char16_t>>, readCharVector),
+    PARCEL_READ_WITH_STATUS(std::vector<char16_t>, readCharVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<android::String16>>>, readString16Vector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<android::String16>>>, readString16Vector),
+    PARCEL_READ_WITH_STATUS(std::vector<android::String16>, readString16Vector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<std::string>>>, readUtf8VectorFromUtf16Vector),
+    PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
 
     [] (const android::Parcel& p, uint8_t /*len*/) {
         FUZZ_LOG() << "about to read flattenable";
@@ -235,8 +235,12 @@
         FUZZ_LOG() << "read lite flattenable: " << status;
     },
 
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // TODO: resizeOutVector
+    PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, resizeOutVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, resizeOutVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, resizeOutVector),
+    PARCEL_READ_WITH_STATUS(std::vector<BigStruct>, resizeOutVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<BigStruct>>, resizeOutVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<BigStruct>>, resizeOutVector),
 
     PARCEL_READ_NO_STATUS(int32_t, readExceptionCode),
     [] (const android::Parcel& p, uint8_t /*len*/) {
@@ -254,10 +258,9 @@
     PARCEL_READ_NO_STATUS(int, readParcelFileDescriptor),
     PARCEL_READ_WITH_STATUS(android::base::unique_fd, readUniqueFileDescriptor),
 
-    // TODO(b/131868573): can force read of arbitrarily sized vector
-    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
-    // PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
-    // PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
+    PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
+    PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
 
     [] (const android::Parcel& p, uint8_t len) {
         FUZZ_LOG() << "about to readBlob";
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 008780c..6b783a4 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -91,28 +91,27 @@
         PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readRequiredParcelFileDescriptor),
         PARCEL_READ(std::string, ndk::AParcel_readString),
         PARCEL_READ(std::optional<std::string>, ndk::AParcel_readString),
-        // TODO(b/131868573): can force process to allocate arbitrary amount of
-        // memory
-        // PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>,
-        // ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>,
-        // ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<float>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<double>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector),
-        // PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector),
-        // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector),
+
+        PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<float>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<double>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector),
+        PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector),
 };
 // clang-format on
diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
index a47b753..f426fd3 100644
--- a/libs/binder/tests/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -95,25 +95,7 @@
     }
 }
 
-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;
-}
-
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    static constexpr size_t kMemLimit = 1 * 1024 * 1024;
-    size_t hardLimit = getHardMemoryLimit();
-    setMemoryLimit(std::min(kMemLimit, hardLimit), hardLimit);
-
     if (size <= 1) return 0;  // no use
 
     // avoid timeouts, see b/142617274, b/142473153
@@ -138,7 +120,5 @@
 
     provider.PickValueInArray(fuzzBackend)(std::move(provider));
 
-    setMemoryLimit(hardLimit, hardLimit);
-
     return 0;
 }
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 3603ebe..8a12aea 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -29,20 +29,6 @@
 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;
@@ -75,10 +61,6 @@
     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{
@@ -113,8 +95,6 @@
         usleep(1);
     }
 
-    setMemoryLimit(hardLimit, hardLimit);
-
     return 0;
 }