Merge "Reduce debuggerd backtrace timeouts in dumpstate"
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index aa0ef25..1c4e63e 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -38,6 +38,7 @@
     ],
 
     init_rc: ["atrace.rc"],
+    required: ["ftrace_synthetic_events.conf"],
 
     product_variables: {
         debuggable: {
@@ -45,3 +46,8 @@
         },
     },
 }
+
+prebuilt_etc {
+    name: "ftrace_synthetic_events.conf",
+    src: "ftrace_synthetic_events.conf",
+}
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 07e586e..6469e95 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -291,12 +291,10 @@
 # Setup synthetic events
     chmod 0666 /sys/kernel/tracing/synthetic_events
     chmod 0666 /sys/kernel/debug/tracing/synthetic_events
+    copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/tracing/synthetic_events
+    copy /system/etc/ftrace_synthetic_events.conf /sys/kernel/debug/tracing/synthetic_events
 
-    # rss_stat_throttled
-    write /sys/kernel/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
-    write /sys/kernel/debug/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
-
-    # allow creating event triggers
+    # allow creating rss_stat event triggers
     chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
     chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
 
@@ -304,6 +302,14 @@
     chmod 0666 /sys/kernel/tracing/events/synthetic/rss_stat_throttled/enable
     chmod 0666 /sys/kernel/debug/tracing/events/synthetic/rss_stat_throttled/enable
 
+    # allow creating suspend_resume triggers
+    chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/trigger
+    chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/trigger
+
+    # allow enabling suspend_resume_minimal
+    chmod 0666 /sys/kernel/tracing/events/synthetic/suspend_resume_minimal/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/synthetic/suspend_resume_minimal/enable
+
 on late-init && property:ro.boot.fastboot.boottrace=enabled
     setprop debug.atrace.tags.enableflags 802922
     setprop persist.traced.enable 0
diff --git a/cmds/atrace/ftrace_synthetic_events.conf b/cmds/atrace/ftrace_synthetic_events.conf
new file mode 100644
index 0000000..e2257fe
--- /dev/null
+++ b/cmds/atrace/ftrace_synthetic_events.conf
@@ -0,0 +1,2 @@
+rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size
+suspend_resume_minimal bool start
diff --git a/cmds/cmd/fuzzer/Android.bp b/cmds/cmd/fuzzer/Android.bp
index a65f6de..faf461a 100644
--- a/cmds/cmd/fuzzer/Android.bp
+++ b/cmds/cmd/fuzzer/Android.bp
@@ -42,5 +42,13 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libcmd",
+        vector: "local_no_privileges_required",
+        service_privilege: "constrained",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5594c26..f1757dc 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -814,6 +814,8 @@
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
+    printf("Bootconfig: ");
+    DumpFileToFd(STDOUT_FILENO, "", "/proc/bootconfig");
     printf("Uptime: ");
     RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
                    CommandOptions::WithTimeout(1).Always().Build());
@@ -1252,7 +1254,8 @@
              dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
              dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
         } else {
-             status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID,
+             status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID |
+                                                       Dumpsys::TYPE_CLIENTS | Dumpsys::TYPE_THREAD,
                                                        service, args);
              if (status == OK) {
                 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
@@ -2797,6 +2800,7 @@
             options->do_screenshot = false;
             break;
         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
+            options->do_vibrate = false;
             options->do_progress_updates = true;
             options->do_screenshot = is_screenshot_requested;
             break;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 7234d41..0012177 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -285,8 +285,8 @@
 
 
     // Other options retain default values
-    EXPECT_TRUE(options_.do_vibrate);
     EXPECT_FALSE(options_.progress_updates_to_socket);
+    EXPECT_FALSE(options_.do_vibrate);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_FALSE(options_.is_remote_mode);
     EXPECT_FALSE(options_.stream_to_socket);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index be4ca43..c4071c6 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -203,6 +203,10 @@
     std::string secondary_dex_de_;
 
     virtual void SetUp() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+        }
+
         setenv("ANDROID_LOG_TAGS", "*:v", 1);
         android::base::InitLogging(nullptr);
         // Initialize the globals holding the file system main paths (/data/, /system/ etc..).
@@ -223,6 +227,10 @@
     }
 
     virtual void TearDown() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP();
+        }
+
         if (!kDebug) {
             service_->controlDexOptBlocking(false);
             service_->destroyAppData(
@@ -966,6 +974,10 @@
 class PrimaryDexReCompilationTest : public DexoptTest {
   public:
     virtual void SetUp() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+        }
+
         DexoptTest::SetUp();
         CompilePrimaryDexOk("verify",
                             DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
@@ -980,6 +992,10 @@
     }
 
     virtual void TearDown() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP();
+        }
+
         first_compilation_odex_fd_.reset(-1);
         first_compilation_vdex_fd_.reset(-1);
         DexoptTest::TearDown();
@@ -1002,6 +1018,10 @@
 
 class ReconcileTest : public DexoptTest {
     virtual void SetUp() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+        }
+
         DexoptTest::SetUp();
         CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
             /*binder_ok*/ true, /*compile_ok*/ true);
@@ -1067,6 +1087,10 @@
     static constexpr const char* kPrimaryProfile = "primary.prof";
 
     virtual void SetUp() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+        }
+
         DexoptTest::SetUp();
         cur_profile_ = create_current_profile_path(
                 kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false);
@@ -1440,6 +1464,9 @@
     std::vector<int64_t> extra_ce_data_inodes_;
 
     virtual void SetUp() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
+        }
 
         ProfileTest::SetUp();
         intial_android_profiles_dir = android_profiles_dir;
@@ -1453,6 +1480,10 @@
     }
 
     virtual void TearDown() {
+        if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
+            GTEST_SKIP();
+        }
+
         android_profiles_dir = intial_android_profiles_dir;
         deleteAppProfilesForBootMerge();
         ProfileTest::TearDown();
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 1386660..d73a30b 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -72,6 +72,7 @@
 
 cc_test {
     name: "servicemanager_test",
+    host_supported: true,
     test_suites: ["device-tests"],
     defaults: ["servicemanager_defaults"],
     srcs: [
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index bec262e..980682d 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -337,34 +337,38 @@
     auto ctx = mAccess->getCallingContext();
 
     if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services");
+        return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services.");
     }
 
     if (!mAccess->canAdd(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     if (binder == nullptr) {
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder");
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder.");
     }
 
     if (!isValidServiceName(name)) {
         ALOGE("Invalid service name: %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
     }
 
 #ifndef VENDORSERVICEMANAGER
     if (!meetsDeclarationRequirements(binder, name)) {
         // already logged
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error");
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error.");
     }
 #endif  // !VENDORSERVICEMANAGER
 
+    if ((dumpPriority & DUMP_FLAG_PRIORITY_ALL) == 0) {
+        ALOGW("Dump flag priority is not set when adding %s", name.c_str());
+    }
+
     // implicitly unlinked when the binder is removed
     if (binder->remoteBinder() != nullptr &&
         binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
         ALOGE("Could not linkToDeath when adding %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
     }
 
     auto it = mNameToService.find(name);
@@ -418,7 +422,7 @@
 
 Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
     if (!mAccess->canList(mAccess->getCallingContext())) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     size_t toReserve = 0;
@@ -452,18 +456,18 @@
 
     if (!isValidServiceName(name)) {
         ALOGE("Invalid service name: %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
     }
 
     if (callback == nullptr) {
-        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+        return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null callback.");
     }
 
     if (OK !=
         IInterface::asBinder(callback)->linkToDeath(
                 sp<ServiceManager>::fromExisting(this))) {
         ALOGE("Could not linkToDeath when adding %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't link to death.");
     }
 
     mNameToRegistrationCallback[name].push_back(callback);
@@ -483,7 +487,7 @@
     auto ctx = mAccess->getCallingContext();
 
     if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     bool found = false;
@@ -495,7 +499,7 @@
 
     if (!found) {
         ALOGE("Trying to unregister callback, but none exists %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Nothing to unregister.");
     }
 
     return Status::ok();
@@ -505,7 +509,7 @@
     auto ctx = mAccess->getCallingContext();
 
     if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     *outReturn = false;
@@ -533,7 +537,7 @@
     }
 
     if (outReturn->size() == 0 && allInstances.size() != 0) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     return Status::ok();
@@ -544,7 +548,7 @@
     auto ctx = mAccess->getCallingContext();
 
     if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     *outReturn = std::nullopt;
@@ -573,7 +577,7 @@
     }
 
     if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     return Status::ok();
@@ -584,7 +588,7 @@
     auto ctx = mAccess->getCallingContext();
 
     if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     *outReturn = std::nullopt;
@@ -653,36 +657,37 @@
 Status ServiceManager::registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                               const sp<IClientCallback>& cb) {
     if (cb == nullptr) {
-        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+        return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Callback null.");
     }
 
     auto ctx = mAccess->getCallingContext();
     if (!mAccess->canAdd(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     auto serviceIt = mNameToService.find(name);
     if (serviceIt == mNameToService.end()) {
         ALOGE("Could not add callback for nonexistent service: %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Service doesn't exist.");
     }
 
     if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
         ALOGW("Only a server can register for client callbacks (for %s)", name.c_str());
-        return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
+        return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+                                         "Only service can register client callback for itself.");
     }
 
     if (serviceIt->second.binder != service) {
         ALOGW("Tried to register client callback for %s but a different service is registered "
               "under this name.",
               name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Service mismatch.");
     }
 
     if (OK !=
         IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) {
         ALOGE("Could not linkToDeath when adding client callback for %s", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
     }
 
     mNameToClientCallback[name].push_back(cb);
@@ -796,24 +801,25 @@
 
 Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IBinder>& binder) {
     if (binder == nullptr) {
-        return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+        return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null service.");
     }
 
     auto ctx = mAccess->getCallingContext();
     if (!mAccess->canAdd(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     auto serviceIt = mNameToService.find(name);
     if (serviceIt == mNameToService.end()) {
         ALOGW("Tried to unregister %s, but that service wasn't registered to begin with.",
               name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Service not registered.");
     }
 
     if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
         ALOGW("Only a server can unregister itself (for %s)", name.c_str());
-        return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
+        return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+                                         "Service can only unregister itself.");
     }
 
     sp<IBinder> storedBinder = serviceIt->second.binder;
@@ -821,14 +827,16 @@
     if (binder != storedBinder) {
         ALOGW("Tried to unregister %s, but a different service is registered under this name.",
               name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+                                         "Different service registered under this name.");
     }
 
     // important because we don't have timer-based guarantees, we don't want to clear
     // this
     if (serviceIt->second.guaranteeClient) {
         ALOGI("Tried to unregister %s, but there is about to be a client.", name.c_str());
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+                                         "Can't unregister, pending client.");
     }
 
     // - kernel driver will hold onto one refcount (during this transaction)
@@ -843,7 +851,8 @@
         // help reduce thrashing, but we should be able to remove it.
         serviceIt->second.guaranteeClient = true;
 
-        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
+                                         "Can't unregister, known client.");
     }
 
     ALOGI("Unregistering %s", name.c_str());
@@ -854,7 +863,7 @@
 
 Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
     if (!mAccess->canList(mAccess->getCallingContext())) {
-        return Status::fromExceptionCode(Status::EX_SECURITY);
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
     outReturn->reserve(mNameToService.size());
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2f58e12..1f1fafc 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -359,6 +359,7 @@
 
 cc_library_static {
     name: "libbinder_rpc_no_kernel",
+    vendor_available: true,
     defaults: [
         "libbinder_common_defaults",
         "libbinder_android_defaults",
@@ -411,6 +412,7 @@
 cc_defaults {
     name: "libbinder_tls_defaults",
     defaults: ["libbinder_tls_shared_deps"],
+    vendor_available: true,
     host_supported: true,
 
     header_libs: [
@@ -437,7 +439,7 @@
     defaults: ["libbinder_tls_defaults"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libbinder_trusty",
     vendor: true,
     srcs: [
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 0d06e9e..851b407 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -295,7 +295,8 @@
 bool RpcServer::shutdown() {
     RpcMutexUniqueLock _l(mLock);
     if (mShutdownTrigger == nullptr) {
-        LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown?)");
+        LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed (already shutdown, or not "
+                       "joined yet?)");
         return false;
     }
 
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 8b3ddfb..d5a6da2 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -54,7 +54,7 @@
             }
 
             LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
-            return -savedErrno;
+            return adjustStatus(-savedErrno);
         }
 
         if (pfd.revents & POLLNVAL) {
@@ -87,8 +87,10 @@
                                 "File descriptors are not supported on Trusty yet");
             return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
         };
-        return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn, "tipc_send",
-                                        POLLOUT, altPoll);
+
+        status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn,
+                                                   "tipc_send", POLLOUT, altPoll);
+        return adjustStatus(status);
     }
 
     status_t interruptableReadFully(
@@ -121,13 +123,26 @@
 
             return processSize;
         };
-        return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read", POLLIN,
-                                        altPoll);
+
+        status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read",
+                                                   POLLIN, altPoll);
+        return adjustStatus(status);
     }
 
     bool isWaiting() override { return mSocket.isInPollingState(); }
 
 private:
+    status_t adjustStatus(status_t status) {
+        if (status == -ENOTCONN) {
+            // TIPC returns ENOTCONN on disconnect, but that's basically
+            // the same as DEAD_OBJECT and the latter is the common libbinder
+            // error code for dead connections
+            return DEAD_OBJECT;
+        }
+
+        return status;
+    }
+
     status_t fillReadBuffer() {
         if (mReadBufferPos < mReadBufferSize) {
             return OK;
@@ -167,7 +182,7 @@
                     continue;
                 } else {
                     LOG_RPC_DETAIL("RpcTransport fillBuffer(): %s", strerror(savedErrno));
-                    return -savedErrno;
+                    return adjustStatus(-savedErrno);
                 }
             } else {
                 mReadBufferSize = static_cast<size_t>(processSize);
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 07b38d7..41707d4 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -79,6 +79,12 @@
     },
     {
       "name": "rustBinderSerializationTest"
+    },
+    {
+      "name": "libbinder_ndk_bindgen_test"
+    },
+    {
+      "name": "libbinder_rpc_unstable_bindgen_test"
     }
   ],
   "presubmit-large": [
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 0f0d64a..873e955 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,6 +138,7 @@
 
 aidl_interface {
     name: "binderRpcTestIface",
+    vendor_available: true,
     host_supported: true,
     unstable: true,
     srcs: [
@@ -159,6 +160,7 @@
 cc_library_static {
     name: "libbinder_tls_test_utils",
     host_supported: true,
+    vendor_available: true,
     target: {
         darwin: {
             enabled: false,
@@ -236,6 +238,13 @@
         "binderRpcUniversalTests.cpp",
     ],
 
+    // This test uses a lot of resources and takes a long time. Due to
+    // design of several tests, it is also very sensitive to resource
+    // contention on the device. b/276820894
+    test_options: {
+        unit_test: false,
+    },
+
     test_suites: ["general-tests"],
     require_root: true,
 
@@ -441,6 +450,37 @@
 }
 
 cc_test {
+    name: "binderRpcToTrustyTest",
+    vendor: true,
+    host_supported: false,
+    defaults: [
+        "binderRpcTest_common_defaults",
+        "binderRpcTest_static_defaults",
+    ],
+
+    srcs: [
+        "binderRpcTest.cpp",
+        "binderRpcTestCommon.cpp",
+        "binderRpcUniversalTests.cpp",
+    ],
+
+    cflags: [
+        "-DBINDER_RPC_TO_TRUSTY_TEST",
+    ],
+
+    static_libs: [
+        // We want to link libbinder statically so we can push the binary
+        // to the device for testing independently of the library
+        "libbinder_rpc_no_kernel",
+        "libbinder_trusty",
+        "libtrusty",
+    ],
+
+    test_suites: ["device-tests"],
+    require_root: true,
+}
+
+cc_test {
     name: "RpcTlsUtilsTest",
     host_supported: true,
     target: {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 8b37ed8..504b3ce 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -28,10 +28,10 @@
 #include <sys/prctl.h>
 #include <sys/socket.h>
 
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
 #include <binder/RpcTransportTipcAndroid.h>
 #include <trusty/tipc.h>
-#endif // __ANDROID_VENDOR__
+#endif // BINDER_RPC_TO_TRUSTY_TEST
 
 #include "binderRpcTestCommon.h"
 #include "binderRpcTestFixture.h"
@@ -50,7 +50,7 @@
 constexpr bool kEnableSharedLibs = true;
 #endif
 
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
 constexpr char kTrustyIpcDevice[] = "/dev/trusty-ipc-dev0";
 #endif
 
@@ -214,6 +214,7 @@
     return serverFd;
 }
 
+#ifndef BINDER_RPC_TO_TRUSTY_TEST
 static base::unique_fd connectToUnixBootstrap(const RpcTransportFd& transportFd) {
     base::unique_fd sockClient, sockServer;
     if (!base::Socketpair(SOCK_STREAM, &sockClient, &sockServer)) {
@@ -232,6 +233,7 @@
     }
     return std::move(sockClient);
 }
+#endif // BINDER_RPC_TO_TRUSTY_TEST
 
 std::unique_ptr<RpcTransportCtxFactory> BinderRpc::newFactory(RpcSecurity rpcSecurity) {
     return newTlsFactory(rpcSecurity);
@@ -308,7 +310,7 @@
     for (size_t i = 0; i < options.numSessions; i++) {
         std::unique_ptr<RpcTransportCtxFactory> factory;
         if (socketType == SocketType::TIPC) {
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
             factory = RpcTransportCtxFactoryTipcAndroid::make();
 #else
             LOG_ALWAYS_FATAL("TIPC socket type only supported on vendor");
@@ -378,11 +380,18 @@
                 break;
             case SocketType::TIPC:
                 status = session->setupPreconnectedClient({}, [=]() {
-#ifdef __ANDROID_VENDOR__
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
                     auto port = trustyIpcPort(serverVersion);
-                    int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
-                    return tipcFd >= 0 ? android::base::unique_fd(tipcFd)
-                                       : android::base::unique_fd();
+                    for (size_t i = 0; i < 5; i++) {
+                        // Try to connect several times,
+                        // in case the service is slow to start
+                        int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
+                        if (tipcFd >= 0) {
+                            return android::base::unique_fd(tipcFd);
+                        }
+                        usleep(50000);
+                    }
+                    return android::base::unique_fd();
 #else
                     LOG_ALWAYS_FATAL("Tried to connect to Trusty outside of vendor");
                     return android::base::unique_fd();
@@ -1102,6 +1111,15 @@
     ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
 }
 
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
+INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
+                        ::testing::Combine(::testing::Values(SocketType::TIPC),
+                                           ::testing::Values(RpcSecurity::RAW),
+                                           ::testing::ValuesIn(testVersions()),
+                                           ::testing::ValuesIn(testVersions()),
+                                           ::testing::Values(true), ::testing::Values(true)),
+                        BinderRpc::PrintParamInfo);
+#else // BINDER_RPC_TO_TRUSTY_TEST
 static bool testSupportVsockLoopback() {
     // We don't need to enable TLS to know if vsock is supported.
     unsigned int vsockPort = allocateVsockPort();
@@ -1206,21 +1224,6 @@
     return ret;
 }
 
-static std::vector<SocketType> testTipcSocketTypes() {
-#ifdef __ANDROID_VENDOR__
-    auto port = trustyIpcPort(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
-    int tipcFd = tipc_connect(kTrustyIpcDevice, port.c_str());
-    if (tipcFd >= 0) {
-        close(tipcFd);
-        return {SocketType::TIPC};
-    }
-#endif // __ANDROID_VENDOR__
-
-    // TIPC is not supported on this device, most likely
-    // because /dev/trusty-ipc-dev0 is missing
-    return {};
-}
-
 INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
                         ::testing::Combine(::testing::ValuesIn(testSocketTypes()),
                                            ::testing::ValuesIn(RpcSecurityValues()),
@@ -1230,14 +1233,6 @@
                                            ::testing::Values(false, true)),
                         BinderRpc::PrintParamInfo);
 
-INSTANTIATE_TEST_CASE_P(Trusty, BinderRpc,
-                        ::testing::Combine(::testing::ValuesIn(testTipcSocketTypes()),
-                                           ::testing::Values(RpcSecurity::RAW),
-                                           ::testing::ValuesIn(testVersions()),
-                                           ::testing::ValuesIn(testVersions()),
-                                           ::testing::Values(true), ::testing::Values(true)),
-                        BinderRpc::PrintParamInfo);
-
 class BinderRpcServerRootObject
       : public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
 
@@ -2006,6 +2001,7 @@
                          testing::Values(RpcKeyFormat::PEM, RpcKeyFormat::DER),
                          testing::ValuesIn(testVersions())),
         RpcTransportTlsKeyTest::PrintParamInfo);
+#endif // BINDER_RPC_TO_TRUSTY_TEST
 
 } // namespace android
 
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 768fbe1..46d387c 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -367,13 +367,15 @@
         FUZZ_LOG() << "about to call readFromParcel() with status for SingleDataParcelable";
         parcelables::SingleDataParcelable singleDataParcelable;
         status_t status = singleDataParcelable.readFromParcel(&p);
-        FUZZ_LOG() <<" status: " << status;
+        FUZZ_LOG() << " status: " << status;
     },
     [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
         FUZZ_LOG() << "about to call readFromParcel() with status for GenericDataParcelable";
         parcelables::GenericDataParcelable genericDataParcelable;
         status_t status = genericDataParcelable.readFromParcel(&p);
-        FUZZ_LOG() <<" status: " << status;
+        FUZZ_LOG() << " status: " << status;
+        std::string toString = genericDataParcelable.toString();
+        FUZZ_LOG() << " toString() result: " << toString;
     },
 };
 // clang-format on
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 08eb27a..3a1471e 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -198,6 +198,8 @@
             aidl::parcelables::GenericDataParcelable genericDataParcelable;
             binder_status_t status = genericDataParcelable.readFromParcel(p.aParcel());
             FUZZ_LOG() << "status: " << status;
+            std::string toString = genericDataParcelable.toString();
+            FUZZ_LOG() << "toString() result: " << toString;
         },
         [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) {
             FUZZ_LOG() << "about to marshal AParcel";
diff --git a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
index f1079e9..dd08f72 100644
--- a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
@@ -16,10 +16,23 @@
 package parcelables;
 
 parcelable GenericDataParcelable {
+    enum JustSomeEnum {
+        SOME_ENUMERATOR,
+        ANOTHER_ENUMERATOR,
+        MAYBE_ONE_MORE_ENUMERATOR,
+    }
+
+    const int COOL_CONSTANT = 0x1234;
+
     int data;
     float majorVersion;
     float minorVersion;
     IBinder binder;
     ParcelFileDescriptor fileDescriptor;
     int[] array;
-}
\ No newline at end of file
+    String greatString;
+    @utf8InCpp
+    String greaterString;
+    @nullable String nullableString;
+    JustSomeEnum gretEnum = JustSomeEnum.ANOTHER_ENUMERATOR;
+}
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index 109da75..3a99606 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -154,8 +154,18 @@
     return NO_ERROR;
 }
 
-void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/,
-                                       void* /*ctx*/) {}
+void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
+    auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
+    if (channelContext == nullptr) {
+        // Connections marked "incoming" (outgoing from the server's side)
+        // do not have a valid channel context because joinFn does not get
+        // called for them. We ignore them here.
+        return;
+    }
+
+    auto& session = channelContext->session;
+    (void)session->shutdownAndWait(false);
+}
 
 void RpcServerTrusty::handleChannelCleanup(void* ctx) {
     auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
diff --git a/libs/binder/trusty/binderRpcTest/rules.mk b/libs/binder/trusty/binderRpcTest/rules.mk
index ae39492..975f689 100644
--- a/libs/binder/trusty/binderRpcTest/rules.mk
+++ b/libs/binder/trusty/binderRpcTest/rules.mk
@@ -32,4 +32,8 @@
 	trusty/user/base/lib/googletest \
 	trusty/user/base/lib/libstdc++-trusty \
 
+# TEST_P tests from binderRpcUniversalTests.cpp don't get linked in
+# unless we pass in --whole-archive to the linker (b/275620340).
+MODULE_USE_WHOLE_ARCHIVE := true
+
 include make/trusted_app.mk
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
index d086b49..a8f2cbf 100644
--- a/libs/binderdebug/BinderDebug.cpp
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -48,14 +48,12 @@
             return -errno;
         }
     }
-    static const std::regex kContextLine("^context (\\w+)$");
 
     bool isDesiredContext = false;
     std::string line;
-    std::smatch match;
     while (getline(ifs, line)) {
-        if (std::regex_search(line, match, kContextLine)) {
-            isDesiredContext = match.str(1) == contextName;
+        if (base::StartsWith(line, "context")) {
+            isDesiredContext = base::Split(line, " ").back() == contextName;
             continue;
         }
         if (!isDesiredContext) {
@@ -66,57 +64,72 @@
     return OK;
 }
 
+// Examples of what we are looking at:
+// node 66730: u00007590061890e0 c0000759036130950 pri 0:120 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 tr 1 proc 2300 1790
+// thread 2999: l 00 need_return 1 tr 0
 status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo) {
     std::smatch match;
     static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
     static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)");
     std::string contextStr = contextToString(context);
     status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
-        if (std::regex_search(line, match, kReferencePrefix)) {
-            const std::string& ptrString = "0x" + match.str(2); // use number after c
-            uint64_t ptr;
-            if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
-                // Should not reach here, but just be tolerant.
-                return;
-            }
-            const std::string proc = " proc ";
-            auto pos = line.rfind(proc);
-            if (pos != std::string::npos) {
-                for (const std::string& pidStr : base::Split(line.substr(pos + proc.size()), " ")) {
-                    int32_t pid;
-                    if (!::android::base::ParseInt(pidStr, &pid)) {
+        if (base::StartsWith(line, "  node")) {
+            std::vector<std::string> splitString = base::Tokenize(line, " ");
+            bool pids = false;
+            uint64_t ptr = 0;
+            for (const auto& token : splitString) {
+                if (base::StartsWith(token, "u")) {
+                    const std::string ptrString = "0x" + token.substr(1);
+                    if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+                        LOG(ERROR) << "Failed to parse pointer: " << ptrString;
                         return;
                     }
-                    pidInfo->refPids[ptr].push_back(pid);
+                } else {
+                    // The last numbers in the line after "proc" are all client PIDs
+                    if (token == "proc") {
+                        pids = true;
+                    } else if (pids) {
+                        int32_t pid;
+                        if (!::android::base::ParseInt(token, &pid)) {
+                            LOG(ERROR) << "Failed to parse pid int: " << token;
+                            return;
+                        }
+                        if (ptr == 0) {
+                            LOG(ERROR) << "We failed to parse the pointer, so we can't add the refPids";
+                            return;
+                        }
+                        pidInfo->refPids[ptr].push_back(pid);
+                    }
                 }
             }
+        } else if (base::StartsWith(line, "  thread")) {
+            auto pos = line.find("l ");
+            if (pos != std::string::npos) {
+                // "1" is waiting in binder driver
+                // "2" is poll. It's impossible to tell if these are in use.
+                //     and HIDL default code doesn't use it.
+                bool isInUse = line.at(pos + 2) != '1';
+                // "0" is a thread that has called into binder
+                // "1" is looper thread
+                // "2" is main looper thread
+                bool isBinderThread = line.at(pos + 3) != '0';
+                if (!isBinderThread) {
+                    return;
+                }
+                if (isInUse) {
+                    pidInfo->threadUsage++;
+                }
 
-            return;
-        }
-        if (std::regex_search(line, match, kThreadPrefix)) {
-            // "1" is waiting in binder driver
-            // "2" is poll. It's impossible to tell if these are in use.
-            //     and HIDL default code doesn't use it.
-            bool isInUse = match.str(1) != "1";
-            // "0" is a thread that has called into binder
-            // "1" is looper thread
-            // "2" is main looper thread
-            bool isBinderThread = match.str(2) != "0";
-            if (!isBinderThread) {
-                return;
+                pidInfo->threadCount++;
             }
-            if (isInUse) {
-                pidInfo->threadUsage++;
-            }
-
-            pidInfo->threadCount++;
-            return;
         }
-        return;
     });
     return ret;
 }
 
+// Examples of what we are looking at:
+// ref 52493: desc 910 node 52492 s 1 w 1 d 0000000000000000
+// node 29413: u00007803fc982e80 c000078042c982210 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 tr 1 proc 488 683
 status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
                              int32_t handle, std::vector<pid_t>* pids) {
     std::smatch match;
@@ -124,51 +137,64 @@
     std::string contextStr = contextToString(context);
     int32_t node;
     status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
-        if (std::regex_search(line, match, kNodeNumber)) {
-            const std::string& descString = match.str(1);
-            int32_t desc;
-            if (!::android::base::ParseInt(descString.c_str(), &desc)) {
-                LOG(ERROR) << "Failed to parse desc int: " << descString;
-                return;
-            }
-            if (handle != desc) {
-                return;
-            }
-            const std::string& nodeString = match.str(2);
-            if (!::android::base::ParseInt(nodeString.c_str(), &node)) {
-                LOG(ERROR) << "Failed to parse node int: " << nodeString;
-                return;
-            }
+        if (!base::StartsWith(line, "  ref")) return;
+
+        std::vector<std::string> splitString = base::Tokenize(line, " ");
+        if (splitString.size() < 12) {
+            LOG(ERROR) << "Failed to parse binder_logs ref entry. Expecting size greater than 11, but got: " << splitString.size();
             return;
         }
-        return;
+        int32_t desc;
+        if (!::android::base::ParseInt(splitString[3].c_str(), &desc)) {
+            LOG(ERROR) << "Failed to parse desc int: " << splitString[3];
+            return;
+        }
+        if (handle != desc) {
+            return;
+        }
+        if (!::android::base::ParseInt(splitString[5].c_str(), &node)) {
+            LOG(ERROR) << "Failed to parse node int: " << splitString[5];
+            return;
+        }
+        LOG(INFO) << "Parsed the node: " << node;
     });
     if (ret != OK) {
         return ret;
     }
-    static const std::regex kClients("^\\s+node\\s+(\\d+).*proc\\s+([\\d+\\s*]*)");
+
     ret = scanBinderContext(servicePid, contextStr, [&](const std::string& line) {
-        if (std::regex_search(line, match, kClients)) {
-            const std::string nodeString = match.str(1);
-            int32_t matchedNode;
-            if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
-                LOG(ERROR) << "Failed to parse node int: " << nodeString;
-                return;
-            }
-            if (node != matchedNode) {
-                return;
-            }
-            const std::string clients = match.str(2);
-            for (const std::string& pidStr : base::Split(clients, " ")) {
+        if (!base::StartsWith(line, "  node")) return;
+
+        std::vector<std::string> splitString = base::Tokenize(line, " ");
+        if (splitString.size() < 21) {
+            LOG(ERROR) << "Failed to parse binder_logs node entry. Expecting size greater than 20, but got: " << splitString.size();
+            return;
+        }
+
+        // remove the colon
+        const std::string nodeString = splitString[1].substr(0, splitString[1].size() - 1);
+        int32_t matchedNode;
+        if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
+            LOG(ERROR) << "Failed to parse node int: " << nodeString;
+            return;
+        }
+
+        if (node != matchedNode) {
+            return;
+        }
+        bool pidsSection = false;
+        for (const auto& token : splitString) {
+            if (token == "proc") {
+                pidsSection = true;
+            } else if (pidsSection == true) {
                 int32_t pid;
-                if (!::android::base::ParseInt(pidStr, &pid)) {
+                if (!::android::base::ParseInt(token.c_str(), &pid)) {
+                    LOG(ERROR) << "Failed to parse PID int: " << token;
                     return;
                 }
                 pids->push_back(pid);
             }
-            return;
         }
-        return;
     });
     return ret;
 }
diff --git a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
index a3e5026..54259d2 100644
--- a/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
+++ b/libs/binderthreadstate/include/binderthreadstate/CallerUtils.h
@@ -36,8 +36,12 @@
 // Based on where we are in recursion of nested binder/hwbinder calls, determine
 // which one we are closer to.
 inline static BinderCallType getCurrentServingCall() {
-    const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
-    const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+    auto* hwState = android::hardware::IPCThreadState::selfOrNull();
+    auto* state = android::IPCThreadState::selfOrNull();
+
+    // getServingStackPointer can also return nullptr
+    const void* hwbinderSp = hwState ? hwState->getServingStackPointer() : nullptr;
+    const void* binderSp = state ? state->getServingStackPointer() : nullptr;
 
     if (hwbinderSp == nullptr && binderSp == nullptr) return BinderCallType::NONE;
     if (hwbinderSp == nullptr) return BinderCallType::BINDER;
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index df1f35d..b5c4010 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -16,11 +16,16 @@
 
 #include <BnAidlStuff.h>
 #include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binderthreadstate/CallerUtils.h>
 #include <binderthreadstateutilstest/1.0/IHidlStuff.h>
 #include <gtest/gtest.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
+
+#include <thread>
+
 #include <linux/prctl.h>
 #include <sys/prctl.h>
 
@@ -154,6 +159,20 @@
     EXPECT_TRUE(server->callLocal().isOk());
 }
 
+TEST(BinderThreadState, DoesntInitializeBinderDriver) {
+    // this is on another thread, because it's testing thread-specific
+    // state and we expect it not to be initialized.
+    std::thread([&] {
+        EXPECT_EQ(nullptr, android::IPCThreadState::selfOrNull());
+        EXPECT_EQ(nullptr, android::hardware::IPCThreadState::selfOrNull());
+
+        (void)getCurrentServingCall();
+
+        EXPECT_EQ(nullptr, android::IPCThreadState::selfOrNull());
+        EXPECT_EQ(nullptr, android::hardware::IPCThreadState::selfOrNull());
+    }).join();
+}
+
 TEST(BindThreadState, RemoteHidlCall) {
     auto stuff = IHidlStuff::getService(id2name(kP1Id));
     ASSERT_NE(nullptr, stuff);
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index b2e069c..2e0add5 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware_buffer.h>
 #include <android/hardware_buffer_aidl.h>
+#include <android/binder_libbinder.h>
 #include <vndk/hardware_buffer.h>
 
 #include <errno.h>
@@ -34,9 +35,6 @@
 #include <android/hardware/graphics/common/1.1/types.h>
 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
 
-// TODO: Better way to handle this
-#include "../binder/ndk/parcel_internal.h"
-
 static constexpr int kFdBufferSize = 128 * sizeof(int);  // 128 ints
 
 using namespace android;
@@ -421,7 +419,7 @@
         AHardwareBuffer* _Nullable* _Nonnull outBuffer) {
     if (!parcel || !outBuffer) return STATUS_BAD_VALUE;
     auto buffer = sp<GraphicBuffer>::make();
-    status_t status = parcel->get()->read(*buffer);
+    status_t status = AParcel_viewPlatformParcel(parcel)->read(*buffer);
     if (status != STATUS_OK) return status;
     *outBuffer = AHardwareBuffer_from_GraphicBuffer(buffer.get());
     AHardwareBuffer_acquire(*outBuffer);
@@ -433,7 +431,7 @@
     const GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(buffer);
     if (!gb) return STATUS_BAD_VALUE;
     if (!parcel) return STATUS_BAD_VALUE;
-    return parcel->get()->write(*gb);
+    return AParcel_viewPlatformParcel(parcel)->write(*gb);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 85a5249..21798d0 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -177,14 +177,14 @@
     /**
      * Corresponding formats:
      *   Vulkan: VK_FORMAT_R16_UINT
-     *   OpenGL ES: GR_GL_R16UI
+     *   OpenGL ES: GL_R16UI
      */
     AHARDWAREBUFFER_FORMAT_R16_UINT                 = 0x39,
 
     /**
      * Corresponding formats:
      *   Vulkan: VK_FORMAT_R16G16_UINT
-     *   OpenGL ES: GR_GL_RG16UI
+     *   OpenGL ES: GL_RG16UI
      */
     AHARDWAREBUFFER_FORMAT_R16G16_UINT              = 0x3a,
 
diff --git a/services/gpuservice/vts/Android.bp b/services/gpuservice/vts/Android.bp
index 83a40e7..b6362e2 100644
--- a/services/gpuservice/vts/Android.bp
+++ b/services/gpuservice/vts/Android.bp
@@ -21,7 +21,6 @@
     srcs: ["src/**/*.java"],
     libs: [
         "tradefed",
-        "vts-core-tradefed-harness",
     ],
     test_suites: [
         "general-tests",
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 7d358e1..6b99627 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -21,6 +21,7 @@
         "android.frameworks.stats@1.0",
         "android.frameworks.stats-V2-ndk",
         "libbinder_ndk",
+        "libexpresslog",
         "libhidlbase",
         "liblog",
         "libstatslog",
diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp
index 0f01507..b22f903 100644
--- a/services/stats/StatsAidl.cpp
+++ b/services/stats/StatsAidl.cpp
@@ -22,6 +22,7 @@
 
 #include "StatsAidl.h"
 
+#include <Counter.h>
 #include <log/log.h>
 #include <stats_annotations.h>
 #include <stats_event.h>
@@ -29,11 +30,18 @@
 
 #include <unordered_map>
 
+namespace {
+    static const char* g_AtomErrorMetricName =
+        "statsd_errors.value_report_vendor_atom_errors_count";
+}
+
 namespace aidl {
 namespace android {
 namespace frameworks {
 namespace stats {
 
+using ::android::expresslog::Counter;
+
 template <typename E>
 constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
     return static_cast<typename std::underlying_type<E>::type>(e);
@@ -86,12 +94,14 @@
 ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) {
     if (vendorAtom.atomId < 100000 || vendorAtom.atomId >= 200000) {
         ALOGE("Atom ID %ld is not a valid vendor atom ID", (long)vendorAtom.atomId);
+        Counter::logIncrement(g_AtomErrorMetricName);
         return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                 -1, "Not a valid vendor atom ID");
     }
     if (vendorAtom.reverseDomainName.length() > 50) {
         ALOGE("Vendor atom reverse domain name %s is too long.",
               vendorAtom.reverseDomainName.c_str());
+        Counter::logIncrement(g_AtomErrorMetricName);
         return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                 -1, "Vendor atom reverse domain name is too long");
     }
@@ -100,8 +110,9 @@
 
     if (vendorAtom.atomAnnotations) {
         if (!write_atom_annotations(event, *vendorAtom.atomAnnotations)) {
-            ALOGE("Atom ID %ld has incompatible atom level annotation", (long)vendorAtom.atomId);
             AStatsEvent_release(event);
+            ALOGE("Atom ID %ld has incompatible atom level annotation", (long)vendorAtom.atomId);
+            Counter::logIncrement(g_AtomErrorMetricName);
             return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                     -1, "invalid atom annotation");
         }
@@ -222,6 +233,7 @@
             default: {
                 AStatsEvent_release(event);
                 ALOGE("Atom ID %ld has invalid atomValue.getTag", (long)vendorAtom.atomId);
+                Counter::logIncrement(g_AtomErrorMetricName);
                 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                         -1, "invalid atomValue.getTag");
                 break;
@@ -235,9 +247,10 @@
             VLOG("Atom ID %ld has %ld annotations for field #%ld", (long)vendorAtom.atomId,
                  (long)fieldAnnotations.size(), (long)atomValueIdx + 2);
             if (!write_field_annotations(event, fieldAnnotations)) {
+                AStatsEvent_release(event);
                 ALOGE("Atom ID %ld has incompatible field level annotation for field #%ld",
                       (long)vendorAtom.atomId, (long)atomValueIdx + 2);
-                AStatsEvent_release(event);
+                Counter::logIncrement(g_AtomErrorMetricName);
                 return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                         -1, "invalid atom field annotation");
             }
@@ -249,6 +262,7 @@
     AStatsEvent_release(event);
     if (ret <= 0) {
         ALOGE("Error writing Atom ID %ld. Result: %d", (long)vendorAtom.atomId, ret);
+        Counter::logIncrement(g_AtomErrorMetricName);
     }
     return ret <= 0 ? ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(ret,
                                                                               "report atom failed")
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3875f15..e06f3c4 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -459,6 +459,7 @@
 }
 
 bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
+    if (mDrawingState.surfaceDamageRegion.hasSameRects(surfaceDamage)) return false;
     mDrawingState.surfaceDamageRegion = surfaceDamage;
     mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c2b0a11..905fe40 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -72,6 +72,7 @@
 #include "LayerProtoHelper.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
+#include "MutexUtils.h"
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
 #include "TunnelModeEnabledReporter.h"
@@ -254,10 +255,12 @@
     auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current);
     std::sort(layersInTree.begin(), layersInTree.end());
 
-    traverse(LayerVector::StateSet::Current, [&](Layer* layer) {
-        layer->removeFromCurrentState();
-        layer->removeRelativeZ(layersInTree);
-    });
+    REQUIRE_MUTEX(mFlinger->mStateLock);
+    traverse(LayerVector::StateSet::Current,
+             [&](Layer* layer) REQUIRES(layer->mFlinger->mStateLock) {
+                 layer->removeFromCurrentState();
+                 layer->removeRelativeZ(layersInTree);
+             });
 }
 
 void Layer::addToCurrentState() {
@@ -936,10 +939,12 @@
         mFlinger->mLayersAdded = true;
         // set up SF to handle added color layer
         if (isRemovedFromCurrentState()) {
+            MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
             mDrawingState.bgColorLayer->onRemovedFromCurrentState();
         }
         mFlinger->setTransactionFlags(eTransactionNeeded);
     } else if (mDrawingState.bgColorLayer && alpha == 0) {
+        MUTEX_ALIAS(mFlinger->mStateLock, mDrawingState.bgColorLayer->mFlinger->mStateLock);
         mDrawingState.bgColorLayer->reparent(nullptr);
         mDrawingState.bgColorLayer = nullptr;
         return true;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 200baf0..f0c8ad7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -409,7 +409,7 @@
     virtual ui::LayerStack getLayerStack() const;
     virtual bool setMetadata(const LayerMetadata& data);
     virtual void setChildrenDrawingParent(const sp<Layer>&);
-    virtual bool reparent(const sp<IBinder>& newParentHandle);
+    virtual bool reparent(const sp<IBinder>& newParentHandle) REQUIRES(mFlinger->mStateLock);
     virtual bool setColorTransform(const mat4& matrix);
     virtual mat4 getColorTransform() const;
     virtual bool hasColorTransform() const;
@@ -433,7 +433,8 @@
     virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
     virtual bool setTransactionCompletedListeners(
             const std::vector<sp<CallbackHandle>>& /*handles*/);
-    virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
+    virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace)
+            REQUIRES(mFlinger->mStateLock);
     virtual bool setColorSpaceAgnostic(const bool agnostic);
     virtual bool setDimmingEnabled(const bool dimmingEnabled);
     virtual bool setFrameRateSelectionPriority(int32_t priority);
@@ -715,13 +716,13 @@
     /*
      * Remove from current state and mark for removal.
      */
-    void removeFromCurrentState();
+    void removeFromCurrentState() REQUIRES(mFlinger->mStateLock);
 
     /*
      * called with the state lock from a binder thread when the layer is
      * removed from the current list to the pending removal list
      */
-    void onRemovedFromCurrentState();
+    void onRemovedFromCurrentState() REQUIRES(mFlinger->mStateLock);
 
     /*
      * Called when the layer is added back to the current state list.
@@ -899,6 +900,9 @@
 
     virtual bool simpleBufferUpdate(const layer_state_t&) const { return false; }
 
+    // Exposed so SurfaceFlinger can assert that it's held
+    const sp<SurfaceFlinger> mFlinger;
+
 protected:
     friend class impl::SurfaceInterceptor;
 
@@ -974,9 +978,6 @@
      */
     virtual Rect getInputBounds() const;
 
-    // constant
-    sp<SurfaceFlinger> mFlinger;
-
     bool mPremultipliedAlpha{true};
     const std::string mName;
     const std::string mTransactionName{"TX - " + mName};
diff --git a/services/surfaceflinger/MutexUtils.h b/services/surfaceflinger/MutexUtils.h
index f8be6f3..58f7cb4 100644
--- a/services/surfaceflinger/MutexUtils.h
+++ b/services/surfaceflinger/MutexUtils.h
@@ -50,4 +50,14 @@
     const status_t status;
 };
 
+// Require, under penalty of compilation failure, that the compiler thinks that a mutex is held.
+#define REQUIRE_MUTEX(expr) ([]() REQUIRES(expr) {})()
+
+// Tell the compiler that we know that a mutex is held.
+#define ASSERT_MUTEX(expr) ([]() ASSERT_CAPABILITY(expr) {})()
+
+// Specify that one mutex is an alias for another.
+// (e.g. SurfaceFlinger::mStateLock and Layer::mFlinger->mStateLock)
+#define MUTEX_ALIAS(held, alias) (REQUIRE_MUTEX(held), ASSERT_MUTEX(alias))
+
 } // namespace android
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index 6011d0d..4e7da82 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -4,5 +4,7 @@
 lpy@google.com
 pdwilliams@google.com
 racarr@google.com
+ramindani@google.com
+rnlee@google.com
 scroggo@google.com
 vishnun@google.com
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 5de796d..8df9ba5 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -57,7 +57,4 @@
         "libgtest",
         "libscheduler",
     ],
-    sanitize: {
-        address: true,
-    },
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 866958d..7c3ca4b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4415,6 +4415,7 @@
         }
         return 0;
     }
+    MUTEX_ALIAS(mStateLock, layer->mFlinger->mStateLock);
 
     // Only set by BLAST adapter layers
     if (what & layer_state_t::eProducerDisconnect) {
@@ -7304,6 +7305,7 @@
         ALOGD("Layer was destroyed soon after creation %p", state.layer.unsafe_get());
         return;
     }
+    MUTEX_ALIAS(mStateLock, layer->mFlinger->mStateLock);
 
     sp<Layer> parent;
     bool addToRoot = state.addToRoot;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3e3830d..17541b8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -859,7 +859,7 @@
     // this layer meaning it is entirely safe to destroy all
     // resources associated to this layer.
     void onHandleDestroyed(BBinder* handle, sp<Layer>& layer);
-    void markLayerPendingRemovalLocked(const sp<Layer>& layer);
+    void markLayerPendingRemovalLocked(const sp<Layer>& layer) REQUIRES(mStateLock);
 
     // add a layer to SurfaceFlinger
     status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
index cab33ae..57752b7 100644
--- a/services/surfaceflinger/TEST_MAPPING
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -5,6 +5,14 @@
     },
     {
       "name": "libcompositionengine_test"
+    },
+    {
+      "name": "libscheduler_test"
+    }
+  ],
+  "hwasan-presubmit": [
+    {
+      "name": "libscheduler_test"
     }
   ]
 }
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e9935e5..c46036a 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -508,7 +508,6 @@
         case VK_FORMAT_R8_UNORM:
             native_format = android::PIXEL_FORMAT_R_8;
             break;
-        // TODO: Do we need to query for VK_EXT_rgba10x6_formats here?
         case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
             native_format = android::PIXEL_FORMAT_RGBA_10101010;
             break;
@@ -859,9 +858,23 @@
         }
     }
 
-    // TODO query VK_EXT_rgba10x6_formats support
+    bool rgba10x6_formats_ext = false;
+    uint32_t exts_count;
+    const auto& driver = GetData(pdev).driver;
+    driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
+                                              nullptr);
+    std::vector<VkExtensionProperties> props(exts_count);
+    driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count,
+                                              props.data());
+    for (uint32_t i = 0; i < exts_count; i++) {
+        VkExtensionProperties prop = props[i];
+        if (strcmp(prop.extensionName,
+                   VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME) == 0) {
+            rgba10x6_formats_ext = true;
+        }
+    }
     desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
-    if (AHardwareBuffer_isSupported(&desc)) {
+    if (AHardwareBuffer_isSupported(&desc) && rgba10x6_formats_ext) {
         all_formats.emplace_back(
             VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
                                VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});