Merge "Declare the headers of the ndk_library"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6fb9a4d..5cd2dea 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -193,8 +193,9 @@
         { OPT,      "events/ext4/ext4_da_write_end/enable" },
         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
-        { REQ,      "events/block/block_rq_issue/enable" },
-        { REQ,      "events/block/block_rq_complete/enable" },
+        { REQ,      "events/block/block_bio_queue/enable" },
+        { REQ,      "events/block/block_bio_complete/enable" },
+        { REQ,      "events/ufs/ufshcd_command/enable" },
     } },
     { "mmc",        "eMMC commands",    0, {
         { REQ,      "events/mmc/enable" },
diff --git a/cmds/bugreportz/readme.md b/cmds/bugreportz/readme.md
index eb0d898..3606827 100644
--- a/cmds/bugreportz/readme.md
+++ b/cmds/bugreportz/readme.md
@@ -1,6 +1,6 @@
 # bugreportz protocol
 
-`bugreportz` is used to generate a zippped bugreport whose path is passed back to `adb`, using
+`bugreportz` is used to generate a zipped bugreport whose path is passed back to `adb`, using
 the simple protocol defined below.
 
 # Version 1.1
diff --git a/cmds/dumpstate/TEST_MAPPING b/cmds/dumpstate/TEST_MAPPING
index 839a2c3..649a13e 100644
--- a/cmds/dumpstate/TEST_MAPPING
+++ b/cmds/dumpstate/TEST_MAPPING
@@ -9,15 +9,15 @@
       ]
     },
     {
-      "name": "dumpstate_smoke_test"
-    },
-    {
       "name": "dumpstate_test"
     }
   ],
   "postsubmit": [
     {
       "name": "BugreportManagerTestCases"
+    },
+    {
+      "name": "dumpstate_smoke_test"
     }
   ],
   "imports": [
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 2c8adc7..faf67fd 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -125,8 +125,6 @@
 
 namespace {
 
-constexpr const char* kDump = "android.permission.DUMP";
-
 static binder::Status ok() {
     return binder::Status::ok();
 }
@@ -150,19 +148,6 @@
     return binder::Status::fromServiceSpecificError(code, String8(msg.c_str()));
 }
 
-binder::Status checkPermission(const char* permission) {
-    pid_t pid;
-    uid_t uid;
-
-    if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
-            reinterpret_cast<int32_t*>(&uid))) {
-        return ok();
-    } else {
-        return exception(binder::Status::EX_SECURITY,
-                StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
-    }
-}
-
 binder::Status checkUid(uid_t expectedUid) {
     uid_t uid = IPCThreadState::self()->getCallingUid();
     if (uid == expectedUid || uid == AID_ROOT) {
@@ -400,13 +385,7 @@
     return android::OK;
 }
 
-status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
-    const binder::Status dump_permission = checkPermission(kDump);
-    if (!dump_permission.isOk()) {
-        dprintf(fd, "%s\n", dump_permission.toString8().c_str());
-        return PERMISSION_DENIED;
-    }
-
+status_t InstalldNativeService::dump(int fd, const Vector<String16>& /* args */) {
     {
         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
         dprintf(fd, "Storage mounts:\n");
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 3cfe529..0727383 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -762,4 +762,10 @@
     return Status::ok();
 }
 
+void ServiceManager::clear() {
+    mNameToService.clear();
+    mNameToRegistrationCallback.clear();
+    mNameToClientCallback.clear();
+}
+
 }  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 5e40319..c6db697 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -58,6 +58,12 @@
     void binderDied(const wp<IBinder>& who) override;
     void handleClientCallbacks();
 
+    /**
+     *  This API is added for debug purposes. It clears members which hold service and callback
+     * information.
+     */
+    void clear();
+
 protected:
     virtual void tryStartService(const std::string& name);
 
diff --git a/cmds/servicemanager/ServiceManagerFuzzer.cpp b/cmds/servicemanager/ServiceManagerFuzzer.cpp
index 39f8522..b76a6bd 100644
--- a/cmds/servicemanager/ServiceManagerFuzzer.cpp
+++ b/cmds/servicemanager/ServiceManagerFuzzer.cpp
@@ -29,6 +29,7 @@
     auto accessPtr = std::make_unique<Access>();
     auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
     fuzzService(serviceManager, FuzzedDataProvider(data, size));
+    serviceManager->clear();
 
     return 0;
 }
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 7080c7b..df965ab 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -76,6 +76,7 @@
 
     srcs: [
         "Binder.cpp",
+        "BinderRecordReplay.cpp",
         "BpBinder.cpp",
         "Debug.cpp",
         "FdTrigger.cpp",
@@ -148,7 +149,10 @@
         },
 
         debuggable: {
-            cflags: ["-DBINDER_RPC_DEV_SERVERS"],
+            cflags: [
+                "-DBINDER_RPC_DEV_SERVERS",
+                "-DBINDER_ENABLE_RECORDING",
+            ],
         },
     },
 
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 4029957..481d704 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -21,6 +21,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
+#include <binder/BinderRecordReplay.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
 #include <binder/IPCThreadState.h>
@@ -28,7 +29,9 @@
 #include <binder/IShellCallback.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
+#include <cutils/compiler.h>
 #include <private/android_filesystem_config.h>
+#include <pthread.h>
 #include <utils/misc.h>
 
 #include <inttypes.h>
@@ -60,6 +63,12 @@
 bool kEnableRpcDevServers = false;
 #endif
 
+#ifdef BINDER_ENABLE_RECORDING
+bool kEnableRecording = true;
+#else
+bool kEnableRecording = false;
+#endif
+
 // Log any reply transactions for which the data exceeds this size
 #define LOG_REPLIES_OVER_SIZE (300 * 1024)
 // ---------------------------------------------------------------------------
@@ -265,11 +274,13 @@
     Mutex mLock;
     std::set<sp<RpcServerLink>> mRpcServerLinks;
     BpBinder::ObjectManager mObjects;
+
+    android::base::unique_fd mRecordingFd;
 };
 
 // ---------------------------------------------------------------------------
 
-BBinder::BBinder() : mExtras(nullptr), mStability(0), mParceled(false) {}
+BBinder::BBinder() : mExtras(nullptr), mStability(0), mParceled(false), mRecordingOn(false) {}
 
 bool BBinder::isBinderAlive() const
 {
@@ -281,6 +292,63 @@
     return NO_ERROR;
 }
 
+status_t BBinder::startRecordingTransactions(const Parcel& data) {
+    if (!kEnableRecording) {
+        ALOGW("Binder recording disallowed because recording is not enabled");
+        return INVALID_OPERATION;
+    }
+    if (!kEnableKernelIpc) {
+        ALOGW("Binder recording disallowed because kernel binder is not enabled");
+        return INVALID_OPERATION;
+    }
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (uid != AID_ROOT) {
+        ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
+        return PERMISSION_DENIED;
+    }
+    Extras* e = getOrCreateExtras();
+    AutoMutex lock(e->mLock);
+    if (mRecordingOn) {
+        LOG(INFO) << "Could not start Binder recording. Another is already in progress.";
+        return INVALID_OPERATION;
+    } else {
+        status_t readStatus = data.readUniqueFileDescriptor(&(e->mRecordingFd));
+        if (readStatus != OK) {
+            return readStatus;
+        }
+        mRecordingOn = true;
+        LOG(INFO) << "Started Binder recording.";
+        return NO_ERROR;
+    }
+}
+
+status_t BBinder::stopRecordingTransactions() {
+    if (!kEnableRecording) {
+        ALOGW("Binder recording disallowed because recording is not enabled");
+        return INVALID_OPERATION;
+    }
+    if (!kEnableKernelIpc) {
+        ALOGW("Binder recording disallowed because kernel binder is not enabled");
+        return INVALID_OPERATION;
+    }
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (uid != AID_ROOT) {
+        ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
+        return PERMISSION_DENIED;
+    }
+    Extras* e = getOrCreateExtras();
+    AutoMutex lock(e->mLock);
+    if (mRecordingOn) {
+        e->mRecordingFd.reset();
+        mRecordingOn = false;
+        LOG(INFO) << "Stopped Binder recording.";
+        return NO_ERROR;
+    } else {
+        LOG(INFO) << "Could not stop Binder recording. One is not in progress.";
+        return INVALID_OPERATION;
+    }
+}
+
 const String16& BBinder::getInterfaceDescriptor() const
 {
     static StaticString16 sBBinder(u"BBinder");
@@ -303,6 +371,12 @@
         case PING_TRANSACTION:
             err = pingBinder();
             break;
+        case START_RECORDING_TRANSACTION:
+            err = startRecordingTransactions(data);
+            break;
+        case STOP_RECORDING_TRANSACTION:
+            err = stopRecordingTransactions();
+            break;
         case EXTENSION_TRANSACTION:
             CHECK(reply != nullptr);
             err = reply->writeStrongBinder(getExtension());
@@ -329,6 +403,26 @@
         }
     }
 
+    if (CC_UNLIKELY(kEnableKernelIpc && mRecordingOn && code != START_RECORDING_TRANSACTION)) {
+        Extras* e = mExtras.load(std::memory_order_acquire);
+        AutoMutex lock(e->mLock);
+        if (mRecordingOn) {
+            Parcel emptyReply;
+            auto transaction =
+                    android::binder::debug::RecordedTransaction::fromDetails(code, flags, data,
+                                                                             reply ? *reply
+                                                                                   : emptyReply,
+                                                                             err);
+            if (transaction) {
+                if (status_t err = transaction->dumpToFile(e->mRecordingFd); err != NO_ERROR) {
+                    LOG(INFO) << "Failed to dump RecordedTransaction to file with error " << err;
+                }
+            } else {
+                LOG(INFO) << "Failed to create RecordedTransaction object.";
+            }
+        }
+    }
+
     return err;
 }
 
diff --git a/libs/binder/BinderRecordReplay.cpp b/libs/binder/BinderRecordReplay.cpp
new file mode 100644
index 0000000..90c02a8
--- /dev/null
+++ b/libs/binder/BinderRecordReplay.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2022, 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 <binder/BinderRecordReplay.h>
+#include <algorithm>
+
+using android::Parcel;
+using android::base::unique_fd;
+using android::binder::debug::RecordedTransaction;
+
+#define PADDING8(s) ((8 - (s) % 8) % 8)
+
+static_assert(PADDING8(0) == 0);
+static_assert(PADDING8(1) == 7);
+static_assert(PADDING8(7) == 1);
+static_assert(PADDING8(8) == 0);
+
+// Transactions are sequentially recorded to the file descriptor in the following format:
+//
+// RecordedTransaction.TransactionHeader  (32 bytes)
+// Sent Parcel data                       (getDataSize() bytes)
+// padding                                (enough bytes to align the reply Parcel data to 8 bytes)
+// Reply Parcel data                      (getReplySize() bytes)
+// padding                                (enough bytes to align the next header to 8 bytes)
+// [repeats with next transaction]
+//
+// Warning: This format is non-stable
+
+RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept {
+    mHeader = {t.getCode(),      t.getFlags(),          t.getDataSize(),
+               t.getReplySize(), t.getReturnedStatus(), t.getVersion()};
+    mSent.setData(t.getDataParcel().data(), t.getDataSize());
+    mReply.setData(t.getReplyParcel().data(), t.getReplySize());
+}
+
+std::optional<RecordedTransaction> RecordedTransaction::fromDetails(uint32_t code, uint32_t flags,
+                                                                    const Parcel& dataParcel,
+                                                                    const Parcel& replyParcel,
+                                                                    status_t err) {
+    RecordedTransaction t;
+    t.mHeader = {code,
+                 flags,
+                 static_cast<uint64_t>(dataParcel.dataSize()),
+                 static_cast<uint64_t>(replyParcel.dataSize()),
+                 static_cast<int32_t>(err),
+                 dataParcel.isForRpc() ? static_cast<uint32_t>(1) : static_cast<uint32_t>(0)};
+
+    if (t.mSent.setData(dataParcel.data(), t.getDataSize()) != android::NO_ERROR) {
+        LOG(INFO) << "Failed to set sent parcel data.";
+        return std::nullopt;
+    }
+
+    if (t.mReply.setData(replyParcel.data(), t.getReplySize()) != android::NO_ERROR) {
+        LOG(INFO) << "Failed to set reply parcel data.";
+        return std::nullopt;
+    }
+
+    return std::optional<RecordedTransaction>(std::move(t));
+}
+
+std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd& fd) {
+    RecordedTransaction t;
+    if (!android::base::ReadFully(fd, &t.mHeader, sizeof(mHeader))) {
+        LOG(INFO) << "Failed to read transactionHeader from fd " << fd.get();
+        return std::nullopt;
+    }
+    if (t.getVersion() != 0) {
+        LOG(INFO) << "File corrupted: transaction version is not 0.";
+        return std::nullopt;
+    }
+
+    std::vector<uint8_t> bytes;
+    bytes.resize(t.getDataSize());
+    if (!android::base::ReadFully(fd, bytes.data(), t.getDataSize())) {
+        LOG(INFO) << "Failed to read sent parcel data from fd " << fd.get();
+        return std::nullopt;
+    }
+    if (t.mSent.setData(bytes.data(), t.getDataSize()) != android::NO_ERROR) {
+        LOG(INFO) << "Failed to set sent parcel data.";
+        return std::nullopt;
+    }
+
+    uint8_t padding[7];
+    if (!android::base::ReadFully(fd, padding, PADDING8(t.getDataSize()))) {
+        LOG(INFO) << "Failed to read sent parcel padding from fd " << fd.get();
+        return std::nullopt;
+    }
+    if (std::any_of(padding, padding + 7, [](uint8_t i) { return i != 0; })) {
+        LOG(INFO) << "File corrupted: padding isn't 0.";
+        return std::nullopt;
+    }
+
+    bytes.resize(t.getReplySize());
+    if (!android::base::ReadFully(fd, bytes.data(), t.getReplySize())) {
+        LOG(INFO) << "Failed to read reply parcel data from fd " << fd.get();
+        return std::nullopt;
+    }
+    if (t.mReply.setData(bytes.data(), t.getReplySize()) != android::NO_ERROR) {
+        LOG(INFO) << "Failed to set reply parcel data.";
+        return std::nullopt;
+    }
+
+    if (!android::base::ReadFully(fd, padding, PADDING8(t.getReplySize()))) {
+        LOG(INFO) << "Failed to read parcel padding from fd " << fd.get();
+        return std::nullopt;
+    }
+    if (std::any_of(padding, padding + 7, [](uint8_t i) { return i != 0; })) {
+        LOG(INFO) << "File corrupted: padding isn't 0.";
+        return std::nullopt;
+    }
+
+    return std::optional<RecordedTransaction>(std::move(t));
+}
+
+android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const {
+    if (!android::base::WriteFully(fd, &mHeader, sizeof(mHeader))) {
+        LOG(INFO) << "Failed to write transactionHeader to fd " << fd.get();
+        return UNKNOWN_ERROR;
+    }
+    if (!android::base::WriteFully(fd, mSent.data(), getDataSize())) {
+        LOG(INFO) << "Failed to write sent parcel data to fd " << fd.get();
+        return UNKNOWN_ERROR;
+    }
+    const uint8_t zeros[7] = {0};
+    if (!android::base::WriteFully(fd, zeros, PADDING8(getDataSize()))) {
+        LOG(INFO) << "Failed to write sent parcel padding to fd " << fd.get();
+        return UNKNOWN_ERROR;
+    }
+    if (!android::base::WriteFully(fd, mReply.data(), getReplySize())) {
+        LOG(INFO) << "Failed to write reply parcel data to fd " << fd.get();
+        return UNKNOWN_ERROR;
+    }
+    if (!android::base::WriteFully(fd, zeros, PADDING8(getReplySize()))) {
+        LOG(INFO) << "Failed to write reply parcel padding to fd " << fd.get();
+        return UNKNOWN_ERROR;
+    }
+    return NO_ERROR;
+}
+
+uint32_t RecordedTransaction::getCode() const {
+    return mHeader.code;
+}
+
+uint32_t RecordedTransaction::getFlags() const {
+    return mHeader.flags;
+}
+
+uint64_t RecordedTransaction::getDataSize() const {
+    return mHeader.dataSize;
+}
+
+uint64_t RecordedTransaction::getReplySize() const {
+    return mHeader.replySize;
+}
+
+int32_t RecordedTransaction::getReturnedStatus() const {
+    return mHeader.statusReturned;
+}
+
+uint32_t RecordedTransaction::getVersion() const {
+    return mHeader.version;
+}
+
+const Parcel& RecordedTransaction::getDataParcel() const {
+    return mSent;
+}
+
+const Parcel& RecordedTransaction::getReplyParcel() const {
+    return mReply;
+}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index d9b7231..54d2445 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -30,6 +30,8 @@
 
 #include "BuildFlags.h"
 
+#include <android-base/file.h>
+
 //#undef ALOGV
 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
 
@@ -299,6 +301,18 @@
     return transact(PING_TRANSACTION, data, &reply);
 }
 
+status_t BpBinder::startRecordingBinder(const android::base::unique_fd& fd) {
+    Parcel send, reply;
+    send.writeUniqueFileDescriptor(fd);
+    return transact(START_RECORDING_TRANSACTION, send, &reply);
+}
+
+status_t BpBinder::stopRecordingBinder() {
+    Parcel data, reply;
+    data.markForBinder(sp<BpBinder>::fromExisting(this));
+    return transact(STOP_RECORDING_TRANSACTION, data, &reply);
+}
+
 status_t BpBinder::dump(int fd, const Vector<String16>& args)
 {
     Parcel send;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b50cfb3..bfcf39a 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1318,6 +1318,13 @@
                 LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                 if (error < NO_ERROR) reply.setError(error);
 
+                // b/238777741: clear buffer before we send the reply.
+                // Otherwise, there is a race where the client may
+                // receive the reply and send another transaction
+                // here and the space used by this transaction won't
+                // be freed for the client.
+                buffer.setDataSize(0);
+
                 constexpr uint32_t kForwardReplyFlags = TF_CLEAR_BUF;
                 sendReply(reply, (tr.flags & kForwardReplyFlags));
             } else {
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index c0a8d74..05db774 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "ServiceManager"
+#define LOG_TAG "ServiceManagerCppClient"
 
 #include <binder/IServiceManager.h>
 
@@ -380,6 +380,13 @@
     if (Status status = realGetService(name, &out); !status.isOk()) {
         ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
               status.toString8().c_str());
+        if (0 == ProcessState::self()->getThreadPoolMaxTotalThreadCount()) {
+            ALOGW("Got service, but may be racey because we could not wait efficiently for it. "
+                  "Threadpool has 0 guaranteed threads. "
+                  "Is the threadpool configured properly? "
+                  "See ProcessState::startThreadPool and "
+                  "ProcessState::setThreadPoolMaxThreadCount.");
+        }
         return nullptr;
     }
     if (out != nullptr) return out;
@@ -410,7 +417,9 @@
             if (waiter->mBinder != nullptr) return waiter->mBinder;
         }
 
-        ALOGW("Waited one second for %s (is service started? are binder threads started and available?)", name.c_str());
+        ALOGW("Waited one second for %s (is service started? Number of threads started in the "
+              "threadpool: %zu. Are binder threads started and available?)",
+              name.c_str(), ProcessState::self()->getThreadPoolMaxTotalThreadCount());
 
         // Handle race condition for lazy services. Here is what can happen:
         // - the service dies (not processed by init yet).
diff --git a/libs/binder/RpcTrusty.cpp b/libs/binder/RpcTrusty.cpp
index ea49eef..3b53b05 100644
--- a/libs/binder/RpcTrusty.cpp
+++ b/libs/binder/RpcTrusty.cpp
@@ -26,8 +26,12 @@
 
 using android::base::unique_fd;
 
-sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+        const char* device, const char* port,
+        std::function<void(sp<RpcSession>&)> sessionInitializer) {
     auto session = RpcSession::make(RpcTransportCtxFactoryTipcAndroid::make());
+    // using the callback to initialize the session
+    sessionInitializer(session);
     auto request = [=] {
         int tipcFd = tipc_connect(device, port);
         if (tipcFd < 0) {
@@ -40,6 +44,11 @@
         LOG(ERROR) << "Failed to set up Trusty client. Error: " << statusToString(status).c_str();
         return nullptr;
     }
+    return session;
+}
+
+sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+    auto session = RpcTrustyConnectWithSessionInitializer(device, port, [](auto) {});
     return session->getRootObject();
 }
 
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 88d9ca1..08dbd13 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -105,6 +105,12 @@
     [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd,
                                              const sp<IBinder>& keepAliveBinder);
 
+    // Start recording transactions to the unique_fd in data.
+    // See BinderRecordReplay.h for more details.
+    [[nodiscard]] status_t startRecordingTransactions(const Parcel& data);
+    // Stop the current recording.
+    [[nodiscard]] status_t stopRecordingTransactions();
+
 protected:
     virtual             ~BBinder();
 
@@ -131,7 +137,7 @@
     friend ::android::internal::Stability;
     int16_t mStability;
     bool mParceled;
-    uint8_t mReserved0;
+    bool mRecordingOn;
 
 #ifdef __LP64__
     int32_t mReserved1;
diff --git a/libs/binder/include/binder/BinderRecordReplay.h b/libs/binder/include/binder/BinderRecordReplay.h
new file mode 100644
index 0000000..25ed5e5
--- /dev/null
+++ b/libs/binder/include/binder/BinderRecordReplay.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022, 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcel.h>
+#include <mutex>
+
+namespace android {
+
+namespace binder::debug {
+
+// Warning: Transactions are sequentially recorded to the file descriptor in a
+// non-stable format. A detailed description of the recording format can be found in
+// BinderRecordReplay.cpp.
+
+class RecordedTransaction {
+public:
+    // Filled with the first transaction from fd.
+    static std::optional<RecordedTransaction> fromFile(const android::base::unique_fd& fd);
+    // Filled with the arguments.
+    static std::optional<RecordedTransaction> fromDetails(uint32_t code, uint32_t flags,
+                                                          const Parcel& data, const Parcel& reply,
+                                                          status_t err);
+    RecordedTransaction(RecordedTransaction&& t) noexcept;
+
+    [[nodiscard]] status_t dumpToFile(const android::base::unique_fd& fd) const;
+
+    uint32_t getCode() const;
+    uint32_t getFlags() const;
+    uint64_t getDataSize() const;
+    uint64_t getReplySize() const;
+    int32_t getReturnedStatus() const;
+    uint32_t getVersion() const;
+    const Parcel& getDataParcel() const;
+    const Parcel& getReplyParcel() const;
+
+private:
+    RecordedTransaction() = default;
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wpadded"
+    struct TransactionHeader {
+        uint32_t code = 0;
+        uint32_t flags = 0;
+        uint64_t dataSize = 0;
+        uint64_t replySize = 0;
+        int32_t statusReturned = 0;
+        uint32_t version = 0; // !0 iff Rpc
+    };
+#pragma clang diagnostic pop
+    static_assert(sizeof(TransactionHeader) == 32);
+    static_assert(sizeof(TransactionHeader) % 8 == 0);
+
+    TransactionHeader mHeader;
+    Parcel mSent;
+    Parcel mReply;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-private-field"
+    uint8_t mReserved[40];
+#pragma clang diagnostic pop
+};
+
+} // namespace binder::debug
+
+} // namespace android
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 4172cc5..57e103d 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android-base/unique_fd.h>
 #include <binder/IBinder.h>
 #include <utils/Mutex.h>
 
@@ -89,6 +90,12 @@
 
     std::optional<int32_t> getDebugBinderHandle() const;
 
+    // Start recording transactions to the unique_fd.
+    // See BinderRecordReplay.h for more details.
+    status_t startRecordingBinder(const android::base::unique_fd& fd);
+    // Stop the current recording.
+    status_t stopRecordingBinder();
+
     class ObjectManager {
     public:
         ObjectManager();
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 83aaca7..e75d548 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -56,6 +56,8 @@
         LAST_CALL_TRANSACTION = 0x00ffffff,
 
         PING_TRANSACTION = B_PACK_CHARS('_', 'P', 'N', 'G'),
+        START_RECORDING_TRANSACTION = B_PACK_CHARS('_', 'S', 'R', 'D'),
+        STOP_RECORDING_TRANSACTION = B_PACK_CHARS('_', 'E', 'R', 'D'),
         DUMP_TRANSACTION = B_PACK_CHARS('_', 'D', 'M', 'P'),
         SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_', 'C', 'M', 'D'),
         INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
diff --git a/libs/binder/include_trusty/binder/RpcTrusty.h b/libs/binder/include_trusty/binder/RpcTrusty.h
index f124e0c..b034b9b 100644
--- a/libs/binder/include_trusty/binder/RpcTrusty.h
+++ b/libs/binder/include_trusty/binder/RpcTrusty.h
@@ -22,4 +22,8 @@
 
 sp<IBinder> RpcTrustyConnect(const char* device, const char* port);
 
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+        const char* device, const char* port,
+        std::function<void(sp<RpcSession>&)> sessionInitializer);
+
 } // namespace android
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 0ec6183..a135796 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -30,6 +30,7 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.compos",
+        "com.android.rkpd",
         "com.android.uwb",
         "com.android.virt",
     ],
@@ -80,6 +81,7 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.compos",
+        "com.android.rkpd",
         "com.android.uwb",
         "com.android.virt",
     ],
@@ -138,6 +140,7 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.compos",
+        "com.android.rkpd",
         "com.android.uwb",
         "com.android.virt",
     ],
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index f169390..5ebc27f 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -16,7 +16,7 @@
     ],
     rustlibs: [
         "libbinder_ndk_sys",
-        "libbinder_rpc_unstable_bindgen",
+        "libbinder_rpc_unstable_bindgen_sys",
         "libbinder_rs",
         "libdowncast_rs",
         "liblibc",
@@ -29,6 +29,35 @@
     min_sdk_version: "Tiramisu",
 }
 
+// Build a separate rust_library rather than depending directly on libbinder_rpc_unstable_bindgen,
+// to work around the fact that rust_bindgen targets only produce rlibs and not dylibs, which would
+// result in duplicate conflicting versions of libbinder_ndk_sys. This will hopefully be fixed in
+// the build system, at which point we can delete this target and go back to using
+// libbinder_rpc_unstable_bindgen directly.
+rust_library {
+    name: "libbinder_rpc_unstable_bindgen_sys",
+    crate_name: "binder_rpc_unstable_bindgen",
+    srcs: [
+        ":libbinder_rpc_unstable_bindgen",
+    ],
+    visibility: [":__subpackages__"],
+    rustlibs: [
+        "libbinder_ndk_sys",
+    ],
+    shared_libs: [
+        "libbinder_rpc_unstable",
+        "libutils",
+    ],
+    apex_available: [
+        "com.android.compos",
+        "com.android.uwb",
+        "com.android.virt",
+    ],
+    min_sdk_version: "Tiramisu",
+    lints: "none",
+    clippy_lints: "none",
+}
+
 // TODO(b/184872979): remove once the RPC Binder API is stabilised.
 rust_bindgen {
     name: "libbinder_rpc_unstable_bindgen",
@@ -36,6 +65,15 @@
     crate_name: "binder_rpc_unstable_bindgen",
     visibility: [":__subpackages__"],
     source_stem: "bindings",
+    bindgen_flags: [
+        "--blocklist-type",
+        "AIBinder",
+        "--raw-line",
+        "use binder_ndk_sys::AIBinder;",
+    ],
+    rustlibs: [
+        "libbinder_ndk_sys",
+    ],
     shared_libs: [
         "libbinder_rpc_unstable",
         "libutils",
@@ -52,6 +90,9 @@
     name: "libbinder_rpc_unstable_bindgen_test",
     srcs: [":libbinder_rpc_unstable_bindgen"],
     crate_name: "binder_rpc_unstable_bindgen",
+    rustlibs: [
+        "libbinder_ndk_sys",
+    ],
     test_suites: ["general-tests"],
     auto_gen_config: true,
     clippy_lints: "none",
diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs
index dfc6f06..743800b 100644
--- a/libs/binder/rust/rpcbinder/src/client.rs
+++ b/libs/binder/rust/rpcbinder/src/client.rs
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-use binder::{
-    unstable_api::{new_spibinder, AIBinder},
-    FromIBinder, SpIBinder, StatusCode, Strong,
-};
+use binder::{unstable_api::new_spibinder, FromIBinder, SpIBinder, StatusCode, Strong};
 use std::os::{
     raw::{c_int, c_void},
     unix::io::RawFd,
@@ -27,7 +24,7 @@
 pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
     // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
     // safely be taken by new_spibinder.
-    unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
+    unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port)) }
 }
 
 /// Connects to an RPC Binder server for a particular interface over vsock.
@@ -54,7 +51,7 @@
         new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
             Some(request_fd_wrapper),
             param,
-        ) as *mut AIBinder)
+        ))
     }
 }
 
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
index d98a439..aeb23c6 100644
--- a/libs/binder/rust/rpcbinder/src/server.rs
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-use binder::{unstable_api::AsNative, SpIBinder};
+use binder::{
+    unstable_api::{AIBinder, AsNative},
+    SpIBinder,
+};
 use std::{os::raw, ptr::null_mut};
 
 /// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
@@ -44,7 +47,7 @@
     F: FnOnce(),
 {
     fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
-        let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
+        let service = service.as_native_mut();
         let param = self.as_void_ptr();
 
         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
@@ -106,10 +109,7 @@
     }
 }
 
-unsafe extern "C" fn factory_wrapper(
-    cid: u32,
-    context: *mut raw::c_void,
-) -> *mut binder_rpc_unstable_bindgen::AIBinder {
+unsafe extern "C" fn factory_wrapper(cid: u32, context: *mut raw::c_void) -> *mut AIBinder {
     // SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
     // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
     // pointing to.
@@ -117,7 +117,7 @@
     let factory = factory_ptr.as_mut().unwrap();
 
     if let Some(mut service) = factory(cid) {
-        service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder
+        service.as_native_mut()
     } else {
         null_mut()
     }
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 3a6dadd..dee05d0 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -296,7 +296,7 @@
     /// Must be called with a valid pointer to a `T` object. After this call,
     /// the pointer will be invalid and should not be dereferenced.
     unsafe extern "C" fn on_destroy(object: *mut c_void) {
-        Box::from_raw(object as *mut T);
+        drop(Box::from_raw(object as *mut T));
     }
 
     /// Called whenever a new, local `AIBinder` object is needed of a specific
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index e460d2c..92d132f 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -605,6 +605,7 @@
     shared_libs: [
         "libbinder",
         "liblog",
+        "libcutils",
         "libutils",
         "libutilscallstack",
         "libbase",
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index a2ab8ab..55a3916 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -20,6 +20,7 @@
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcSession.h>
+#include <cutils/trace.h>
 #include <gtest/gtest.h>
 #include <utils/CallStack.h>
 
@@ -223,5 +224,10 @@
         return 1;
     }
     ::testing::InitGoogleTest(&argc, argv);
+
+    // if tracing is enabled, take in one-time cost
+    (void)ATRACE_INIT();
+    (void)ATRACE_GET_ENABLED_TAGS();
+
     return RUN_ALL_TESTS();
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5de08bd..6e1c8ac 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1161,8 +1161,7 @@
 // see ProcessState.cpp BINDER_VM_SIZE = 1MB.
 // This value is not exposed, but some code in the framework relies on being able to use
 // buffers near the cap size.
-// TODO(b/238777741): why do larger values, like 300K fail sometimes
-constexpr size_t kSizeBytesAlmostFull = 100'000;
+constexpr size_t kSizeBytesAlmostFull = 950'000;
 constexpr size_t kSizeBytesOverFull = 1'050'000;
 
 TEST_F(BinderLibTest, GargantuanVectorSent) {
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 2f73137..df1f35d 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -73,6 +73,15 @@
     CHECK(ret.isOk()) << ret;
 }
 
+static std::string getStackPointerDebugInfo() {
+    const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
+    const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+
+    std::stringstream ss;
+    ss << "(hwbinder sp: " << hwbinderSp << " binder sp: " << binderSp << ")";
+    return ss.str();
+}
+
 static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
     return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
 }
@@ -88,17 +97,21 @@
         return android::hardware::Status::ok();
     }
     Return<void> call(int32_t idx) {
+        bool doCallHidl = thisId == kP1Id && idx % 4 < 2;
+
         LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
-                  << " with tid: " << gettid();
-        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+                << " before call " << getStackPointerDebugInfo();
         if (idx > 0) {
-            if (thisId == kP1Id && idx % 4 < 2) {
+            if (doCallHidl) {
                 callHidl(otherId, idx - 1);
             } else {
                 callAidl(otherId, idx - 1);
             }
         }
-        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+                << " after call " << getStackPointerDebugInfo();
         return android::hardware::Status::ok();
     }
 };
@@ -113,17 +126,20 @@
         return Status::ok();
     }
     Status call(int32_t idx) {
+        bool doCallHidl = thisId == kP2Id && idx % 4 < 2;
         LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
-                  << " with tid: " << gettid();
-        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+                << " before call " << getStackPointerDebugInfo();
         if (idx > 0) {
-            if (thisId == kP2Id && idx % 4 < 2) {
+            if (doCallHidl) {
                 callHidl(otherId, idx - 1);
             } else {
                 callAidl(otherId, idx - 1);
             }
         }
-        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+                << " after call " << getStackPointerDebugInfo();
         return Status::ok();
     }
 };
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 13ca9ec..4127f7c 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -929,6 +929,8 @@
         out << ", actionButton=" << std::to_string(event.getActionButton());
     }
     const size_t pointerCount = event.getPointerCount();
+    LOG_ALWAYS_FATAL_IF(pointerCount > MAX_POINTERS, "Too many pointers : pointerCount = %zu",
+                        pointerCount);
     for (size_t i = 0; i < pointerCount; i++) {
         out << ", id[" << i << "]=" << event.getPointerId(i);
         float x = event.getX(i);
diff --git a/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp b/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
index 6f10a67..6a61d36 100644
--- a/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
+++ b/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
@@ -24,14 +24,14 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
-    BitTube bittube(size);
+    sp<BitTube> bittube(new BitTube(size));
     Parcel parcel[5];
-    bittube.writeToParcel(parcel);
+    bittube->writeToParcel(parcel);
     sp<BitTube> tube(new BitTube(size));
-    bittube.sendObjects<uint8_t>(tube, data, size);
+    bittube->sendObjects<uint8_t>(tube, data, size);
     uint8_t recvData[size];
     for (int i = 0; i < size; i++) recvData[i] = fdp.ConsumeIntegral<uint8_t>();
-    bittube.recvObjects<uint8_t>(tube, recvData, size);
+    bittube->recvObjects<uint8_t>(tube, recvData, size);
 
     return 0;
 }
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index f664f2f..62cf255 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -185,7 +185,11 @@
         "libEGL_getProcAddress",
         "libEGL_blobCache",
     ],
-    ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"],
+    ldflags: [
+        "-Wl,--exclude-libs=libEGL_getProcAddress.a",
+        "-Wl,--exclude-libs=libEGL_blobCache.a",
+        "-Wl,--Bsymbolic-functions",
+    ],
     export_include_dirs: ["EGL/include"],
     stubs: {
         symbol_file: "libEGL.map.txt",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 5e9427a..564acc0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3640,6 +3640,8 @@
     target.inputChannel = connection->inputChannel;
     target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
 
+    const bool wasEmpty = connection->outboundQueue.empty();
+
     for (size_t i = 0; i < cancelationEvents.size(); i++) {
         std::unique_ptr<EventEntry> cancelationEventEntry = std::move(cancelationEvents[i]);
         switch (cancelationEventEntry->type) {
@@ -3674,7 +3676,10 @@
                                    InputTarget::FLAG_DISPATCH_AS_IS);
     }
 
-    startDispatchCycleLocked(currentTime, connection);
+    // If the outbound queue was previously empty, start the dispatch cycle going.
+    if (wasEmpty && !connection->outboundQueue.empty()) {
+        startDispatchCycleLocked(currentTime, connection);
+    }
 }
 
 void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
@@ -3708,6 +3713,8 @@
     target.inputChannel = connection->inputChannel;
     target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
 
+    const bool wasEmpty = connection->outboundQueue.empty();
+
     for (std::unique_ptr<EventEntry>& downEventEntry : downEvents) {
         switch (downEventEntry->type) {
             case EventEntry::Type::MOTION: {
@@ -3733,8 +3740,10 @@
         enqueueDispatchEntryLocked(connection, std::move(downEventEntry), target,
                                    InputTarget::FLAG_DISPATCH_AS_IS);
     }
-
-    startDispatchCycleLocked(currentTime, connection);
+    // If the outbound queue was previously empty, start the dispatch cycle going.
+    if (wasEmpty && !connection->outboundQueue.empty()) {
+        startDispatchCycleLocked(currentTime, connection);
+    }
 }
 
 std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(