Merge "Remove VNDK definition(s)" into main
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 9b357e7..fdac5db 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -319,7 +319,7 @@
 # Only create the tracing instance if persist.mm_events.enabled
 # Attempting to remove the tracing instance after it has been created
 # will likely fail with EBUSY as it would be in use by traced_probes.
-on post-fs-data && property:persist.mm_events.enabled=true
+on mm_events_property_available && property:persist.mm_events.enabled=true
 # Create MM Events Tracing Instance for Kmem Activity Trigger
     mkdir /sys/kernel/debug/tracing/instances/mm_events 0755 system system
     mkdir /sys/kernel/tracing/instances/mm_events 0755 system system
@@ -404,6 +404,9 @@
     chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu23/trace
     chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu23/trace
 
+on property:ro.persistent_properties.ready=true
+    trigger mm_events_property_available
+
 # Handle hyp tracing instance
 on late-init && property:ro.boot.hypervisor.vm.supported=1
 
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
index 5f56531..41bfd26 100644
--- a/cmds/bugreport/OWNERS
+++ b/cmds/bugreport/OWNERS
@@ -1,5 +1,5 @@
 set noparent
 
-gavincorkery@google.com
+ronish@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
index 5f56531..41bfd26 100644
--- a/cmds/bugreportz/OWNERS
+++ b/cmds/bugreportz/OWNERS
@@ -1,5 +1,5 @@
 set noparent
 
-gavincorkery@google.com
+ronish@google.com
 nandana@google.com
 jsharkey@android.com
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index ab81ecf..c24bf39 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
-gavincorkery@google.com
+ronish@google.com
 nandana@google.com
 jsharkey@android.com
 smoreland@google.com
\ No newline at end of file
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index befb5d4..c501921 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -4143,14 +4143,14 @@
 }
 
 int read_file_as_long(const char *path, long int *output) {
-    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
-    if (fd < 0) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
+    if (fd.get() < 0) {
         int err = errno;
         MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
         return -1;
     }
     char buffer[50];
-    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer, sizeof(buffer)));
     if (bytes_read == -1) {
         MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
         return -2;
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 97a63ca..03143ae 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -1,6 +1,6 @@
 set noparent
 
-gavincorkery@google.com
+ronish@google.com
 nandana@google.com
 jsharkey@android.com
 
diff --git a/cmds/evemu-record/main.rs b/cmds/evemu-record/main.rs
index c30c00f..db3fd77 100644
--- a/cmds/evemu-record/main.rs
+++ b/cmds/evemu-record/main.rs
@@ -120,7 +120,7 @@
     fn print_in_8_byte_chunks(
         output: &mut impl Write,
         prefix: &str,
-        data: &Vec<u8>,
+        data: &[u8],
     ) -> Result<(), io::Error> {
         for (i, byte) in data.iter().enumerate() {
             if i % 8 == 0 {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 870e8eb..0c1feb8 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -731,16 +731,17 @@
                                   [hashChain](const auto& ret) { *hashChain = std::move(ret); });
         if (!hashRet.isOk()) {
             handleError(TRANSACTION_ERROR, "getHashChain failed: " + hashRet.description());
+            break; // skip getHashChain
         }
         if (static_cast<size_t>(hashIndex) >= hashChain->size()) {
             handleError(BAD_IMPL,
                         "interfaceChain indicates position " + std::to_string(hashIndex) +
                                 " but getHashChain returns " + std::to_string(hashChain->size()) +
                                 " hashes");
-        } else {
-            auto&& hashArray = (*hashChain)[hashIndex];
-            entry->hash = android::base::HexString(hashArray.data(), hashArray.size());
+            break; // skip getHashChain
         }
+        auto&& hashArray = (*hashChain)[hashIndex];
+        entry->hash = android::base::HexString(hashArray.data(), hashArray.size());
     } while (0);
     if (status == OK) {
         entry->serviceStatus = ServiceStatus::ALIVE;
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
index 711038c..8098724 100644
--- a/cmds/servicemanager/Access.cpp
+++ b/cmds/servicemanager/Access.cpp
@@ -22,6 +22,8 @@
 #include <selinux/android.h>
 #include <selinux/avc.h>
 
+#include <sstream>
+
 namespace android {
 
 #ifdef VENDORSERVICEMANAGER
@@ -80,6 +82,12 @@
 }
 #endif
 
+std::string Access::CallingContext::toDebugString() const {
+    std::stringstream ss;
+    ss << "Caller(pid=" << debugPid << ",uid=" << uid << ",sid=" << sid << ")";
+    return ss.str();
+}
+
 Access::Access() {
 #ifdef __ANDROID__
     union selinux_callback cb;
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
index 77c2cd4..4ee9b90 100644
--- a/cmds/servicemanager/Access.h
+++ b/cmds/servicemanager/Access.h
@@ -36,6 +36,8 @@
         pid_t debugPid;
         uid_t uid;
         std::string sid;
+
+        std::string toDebugString() const;
     };
 
     virtual CallingContext getCallingContext();
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index a828b52..a5c0c60 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -115,18 +115,20 @@
     return instance.package() + "." + instance.interface() + "/" + instance.instance();
 }
 
-static bool isVintfDeclared(const std::string& name) {
+static bool isVintfDeclared(const Access::CallingContext& ctx, const std::string& name) {
     NativeName nname;
     if (NativeName::fill(name, &nname)) {
         bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
             if (mwd.manifest->hasNativeInstance(nname.package, nname.instance)) {
-                ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
+                ALOGI("%s Found %s in %s VINTF manifest.", ctx.toDebugString().c_str(),
+                      name.c_str(), mwd.description);
                 return true; // break
             }
             return false; // continue
         });
         if (!found) {
-            ALOGI("Could not find %s in the VINTF manifest.", name.c_str());
+            ALOGI("%s Could not find %s in the VINTF manifest.", ctx.toDebugString().c_str(),
+                  name.c_str());
         }
         return found;
     }
@@ -136,7 +138,8 @@
 
     bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
         if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) {
-            ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
+            ALOGI("%s Found %s in %s VINTF manifest.", ctx.toDebugString().c_str(), name.c_str(),
+                  mwd.description);
             return true; // break
         }
         return false;  // continue
@@ -161,8 +164,9 @@
         }
         // Although it is tested, explicitly rebuilding qualified name, in case it
         // becomes something unexpected.
-        ALOGI("Could not find %s.%s/%s in the VINTF manifest. %s.", aname.package.c_str(),
-              aname.iface.c_str(), aname.instance.c_str(), available.c_str());
+        ALOGI("%s Could not find %s.%s/%s in the VINTF manifest. %s.", ctx.toDebugString().c_str(),
+              aname.package.c_str(), aname.iface.c_str(), aname.instance.c_str(),
+              available.c_str());
     }
 
     return found;
@@ -290,12 +294,13 @@
     return ret;
 }
 
-static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
+static bool meetsDeclarationRequirements(const Access::CallingContext& ctx,
+                                         const sp<IBinder>& binder, const std::string& name) {
     if (!Stability::requiresVintfDeclaration(binder)) {
         return true;
     }
 
-    return isVintfDeclared(name);
+    return isVintfDeclared(ctx, name);
 }
 #endif  // !VENDORSERVICEMANAGER
 
@@ -307,7 +312,7 @@
         // clear this bit so that we can abort in other cases, where it would
         // mean inconsistent logic in servicemanager (unexpected and tested, but
         // the original lazy service impl here had that bug).
-        LOG(WARNING) << "a service was removed when there are clients";
+        ALOGW("A service was removed when there are clients");
     }
 }
 
@@ -423,25 +428,26 @@
     }
 
     if (!isValidServiceName(name)) {
-        ALOGE("Invalid service name: %s", name.c_str());
+        ALOGE("%s Invalid service name: %s", ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
     }
 
 #ifndef VENDORSERVICEMANAGER
-    if (!meetsDeclarationRequirements(binder, name)) {
+    if (!meetsDeclarationRequirements(ctx, binder, name)) {
         // already logged
         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());
+        ALOGW("%s Dump flag priority is not set when adding %s", ctx.toDebugString().c_str(),
+              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());
+        ALOGE("%s Could not linkToDeath when adding %s", ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
     }
 
@@ -543,7 +549,7 @@
     }
 
     if (!isValidServiceName(name)) {
-        ALOGE("Invalid service name: %s", name.c_str());
+        ALOGE("%s Invalid service name: %s", ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
     }
 
@@ -554,7 +560,7 @@
     if (OK !=
         IInterface::asBinder(callback)->linkToDeath(
                 sp<ServiceManager>::fromExisting(this))) {
-        ALOGE("Could not linkToDeath when adding %s", name.c_str());
+        ALOGE("%s Could not linkToDeath when adding %s", ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't link to death.");
     }
 
@@ -586,7 +592,8 @@
     }
 
     if (!found) {
-        ALOGE("Trying to unregister callback, but none exists %s", name.c_str());
+        ALOGE("%s Trying to unregister callback, but none exists %s", ctx.toDebugString().c_str(),
+              name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Nothing to unregister.");
     }
 
@@ -603,7 +610,7 @@
     *outReturn = false;
 
 #ifndef VENDORSERVICEMANAGER
-    *outReturn = isVintfDeclared(name);
+    *outReturn = isVintfDeclared(ctx, name);
 #endif
     return Status::ok();
 }
@@ -735,18 +742,16 @@
 }
 
 void ServiceManager::tryStartService(const Access::CallingContext& ctx, const std::string& name) {
-    ALOGI("Since '%s' could not be found (requested by debug pid %d), trying to start it as a lazy "
-          "AIDL service. (if it's not configured to be a lazy service, it may be stuck starting or "
-          "still starting).",
-          name.c_str(), ctx.debugPid);
+    ALOGI("%s Since '%s' could not be found trying to start it as a lazy AIDL service. (if it's "
+          "not configured to be a lazy service, it may be stuck starting or still starting).",
+          ctx.toDebugString().c_str(), name.c_str());
 
     std::thread([=] {
         if (!base::SetProperty("ctl.interface_start", "aidl/" + name)) {
-            ALOGI("Tried to start aidl service %s as a lazy service, but was unable to. Usually "
-                  "this happens when a "
-                  "service is not installed, but if the service is intended to be used as a "
-                  "lazy service, then it may be configured incorrectly.",
-                  name.c_str());
+            ALOGI("%s Tried to start aidl service %s as a lazy service, but was unable to. Usually "
+                  "this happens when a service is not installed, but if the service is intended to "
+                  "be used as a lazy service, then it may be configured incorrectly.",
+                  ctx.toDebugString().c_str(), name.c_str());
         }
     }).detach();
 }
@@ -764,26 +769,28 @@
 
     auto serviceIt = mNameToService.find(name);
     if (serviceIt == mNameToService.end()) {
-        ALOGE("Could not add callback for nonexistent service: %s", name.c_str());
+        ALOGE("%s Could not add callback for nonexistent service: %s", ctx.toDebugString().c_str(),
+              name.c_str());
         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());
+        ALOGW("%s Only a server can register for client callbacks (for %s)",
+              ctx.toDebugString().c_str(), name.c_str());
         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 "
+        ALOGW("%s Tried to register client callback for %s but a different service is registered "
               "under this name.",
-              name.c_str());
+              ctx.toDebugString().c_str(), name.c_str());
         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());
+        ALOGE("%s Could not linkToDeath when adding client callback for %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
     }
 
@@ -921,13 +928,14 @@
 
     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());
+        ALOGW("%s Tried to unregister %s, but that service wasn't registered to begin with.",
+              ctx.toDebugString().c_str(), name.c_str());
         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());
+        ALOGW("%s Only a server can unregister itself (for %s)", ctx.toDebugString().c_str(),
+              name.c_str());
         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                          "Service can only unregister itself.");
     }
@@ -935,8 +943,8 @@
     sp<IBinder> storedBinder = serviceIt->second.binder;
 
     if (binder != storedBinder) {
-        ALOGW("Tried to unregister %s, but a different service is registered under this name.",
-              name.c_str());
+        ALOGW("%s Tried to unregister %s, but a different service is registered under this name.",
+              ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
                                          "Different service registered under this name.");
     }
@@ -944,7 +952,8 @@
     // 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());
+        ALOGI("%s Tried to unregister %s, but there is about to be a client.",
+              ctx.toDebugString().c_str(), name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
                                          "Can't unregister, pending client.");
     }
@@ -954,7 +963,8 @@
     constexpr size_t kKnownClients = 2;
 
     if (handleServiceClientCallback(kKnownClients, name, false)) {
-        ALOGI("Tried to unregister %s, but there are clients.", name.c_str());
+        ALOGI("%s Tried to unregister %s, but there are clients.", ctx.toDebugString().c_str(),
+              name.c_str());
 
         // Since we had a failed registration attempt, and the HIDL implementation of
         // delaying service shutdown for multiple periods wasn't ported here... this may
@@ -965,7 +975,7 @@
                                          "Can't unregister, known client.");
     }
 
-    ALOGI("Unregistering %s", name.c_str());
+    ALOGI("%s Unregistering %s", ctx.toDebugString().c_str(), name.c_str());
     mNameToService.erase(name);
 
     return Status::ok();
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index e90b8d8..89c6c0f 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -317,6 +317,12 @@
 }
 
 prebuilt_etc {
+    name: "android.hardware.vulkan.compute-0.prebuilt.xml",
+    src: "android.hardware.vulkan.compute-0.xml",
+    defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
     name: "android.hardware.vulkan.level-1.prebuilt.xml",
     src: "android.hardware.vulkan.level-1.xml",
     defaults: ["frameworks_native_data_etc_defaults"],
diff --git a/include/android/OWNERS b/include/android/OWNERS
index 38f9c55..c6cf7ad 100644
--- a/include/android/OWNERS
+++ b/include/android/OWNERS
@@ -1 +1 @@
-per-file input.h, keycodes.h = file:platform/frameworks/base:/INPUT_OWNERS
+per-file input.h,keycodes.h = file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index cce2e46..443cb7e 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -303,7 +303,7 @@
 /**
  * Parameter for ASurfaceTransaction_setVisibility().
  */
-enum {
+enum ASurfaceTransactionVisibility : int8_t {
     ASURFACE_TRANSACTION_VISIBILITY_HIDE = 0,
     ASURFACE_TRANSACTION_VISIBILITY_SHOW = 1,
 };
@@ -315,7 +315,8 @@
  * Available since API level 29.
  */
 void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
-                                       ASurfaceControl* surface_control, int8_t visibility)
+                                       ASurfaceControl* surface_control,
+                                       enum ASurfaceTransactionVisibility visibility)
                                        __INTRODUCED_IN(29);
 
 /**
@@ -346,7 +347,7 @@
  */
 void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
                                    ASurfaceControl* surface_control, AHardwareBuffer* buffer,
-                                   int acquire_fence_fd = -1) __INTRODUCED_IN(29);
+                                   int acquire_fence_fd) __INTRODUCED_IN(29);
 
 /**
  * Updates the color for \a surface_control.  This will make the background color for the
@@ -358,7 +359,7 @@
  */
 void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, float r, float g, float b,
-                                  float alpha, ADataSpace dataspace)
+                                  float alpha, enum ADataSpace dataspace)
                                   __INTRODUCED_IN(29);
 
 /**
@@ -436,7 +437,7 @@
 /**
  * Parameter for ASurfaceTransaction_setBufferTransparency().
  */
-enum {
+enum ASurfaceTransactionTransparency : int8_t {
     ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT = 0,
     ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT = 1,
     ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
@@ -450,7 +451,7 @@
  */
 void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
                                                ASurfaceControl* surface_control,
-                                               int8_t transparency)
+                                               enum ASurfaceTransactionTransparency transparency)
                                                __INTRODUCED_IN(29);
 
 /**
@@ -497,7 +498,7 @@
  * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
-                                            ASurfaceControl* surface_control, ADataSpace data_space)
+                                            ASurfaceControl* surface_control, enum ADataSpace data_space)
                                             __INTRODUCED_IN(29);
 
 /**
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 4a79f9e..9c24dc5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -159,6 +159,11 @@
                 "UtilsHost.cpp",
             ],
         },
+        android: {
+            lto: {
+                thin: true,
+            },
+        },
     },
 
     aidl: {
@@ -219,9 +224,6 @@
         "-performance-move-const-arg", // b/273486801
         "portability*",
     ],
-    lto: {
-        thin: true,
-    },
 }
 
 cc_library_headers {
@@ -664,6 +666,7 @@
         "//packages/modules/Virtualization:__subpackages__",
         "//device/google/cuttlefish/shared/minidroid:__subpackages__",
         "//system/software_defined_vehicle:__subpackages__",
+        "//visibility:any_system_partition",
     ],
 }
 
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 42dd691..54457fc 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -44,6 +44,7 @@
 int BpBinder::sNumTrackedUids = 0;
 std::atomic_bool BpBinder::sCountByUidEnabled(false);
 binder_proxy_limit_callback BpBinder::sLimitCallback;
+binder_proxy_warning_callback BpBinder::sWarningCallback;
 bool BpBinder::sBinderProxyThrottleCreate = false;
 
 static StaticString16 kDescriptorUninit(u"");
@@ -52,6 +53,9 @@
 uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
 // Another arbitrary value a binder count needs to drop below before another callback will be called
 uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
+// Arbitrary value between low and high watermark on a bad behaving app to
+// trigger a warning callback.
+uint32_t BpBinder::sBinderProxyCountWarningWatermark = 2250;
 
 std::atomic<uint32_t> BpBinder::sBinderProxyCount(0);
 std::atomic<uint32_t> BpBinder::sBinderProxyCountWarned(0);
@@ -63,7 +67,8 @@
 
 enum {
     LIMIT_REACHED_MASK = 0x80000000,        // A flag denoting that the limit has been reached
-    COUNTING_VALUE_MASK = 0x7FFFFFFF,       // A mask of the remaining bits for the count value
+    WARNING_REACHED_MASK = 0x40000000,      // A flag denoting that the warning has been reached
+    COUNTING_VALUE_MASK = 0x3FFFFFFF,       // A mask of the remaining bits for the count value
 };
 
 BpBinder::ObjectManager::ObjectManager()
@@ -181,7 +186,13 @@
                 sLastLimitCallbackMap[trackedUid] = trackedValue;
             }
         } else {
-            if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
+            uint32_t currentValue = trackedValue & COUNTING_VALUE_MASK;
+            if (currentValue >= sBinderProxyCountWarningWatermark
+                    && currentValue < sBinderProxyCountHighWatermark
+                    && ((trackedValue & WARNING_REACHED_MASK) == 0)) [[unlikely]] {
+                sTrackingMap[trackedUid] |= WARNING_REACHED_MASK;
+                if (sWarningCallback) sWarningCallback(trackedUid);
+            } else if (currentValue >= sBinderProxyCountHighWatermark) {
                 ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
                       getuid(), trackedUid, trackedValue);
                 sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
@@ -609,11 +620,11 @@
                   binderHandle());
         } else {
             auto countingValue = trackedValue & COUNTING_VALUE_MASK;
-            if ((trackedValue & LIMIT_REACHED_MASK) &&
+            if ((trackedValue & (LIMIT_REACHED_MASK | WARNING_REACHED_MASK)) &&
                 (countingValue <= sBinderProxyCountLowWatermark)) [[unlikely]] {
                 ALOGI("Limit reached bit reset for uid %d (fewer than %d proxies from uid %d held)",
                       getuid(), sBinderProxyCountLowWatermark, mTrackedUid);
-                sTrackingMap[mTrackedUid] &= ~LIMIT_REACHED_MASK;
+                sTrackingMap[mTrackedUid] &= ~(LIMIT_REACHED_MASK | WARNING_REACHED_MASK);
                 sLastLimitCallbackMap.erase(mTrackedUid);
             }
             if (--sTrackingMap[mTrackedUid] == 0) {
@@ -730,15 +741,18 @@
 void BpBinder::disableCountByUid() { sCountByUidEnabled.store(false); }
 void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }
 
-void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
+void BpBinder::setBinderProxyCountEventCallback(binder_proxy_limit_callback cbl,
+                                                binder_proxy_warning_callback cbw) {
     RpcMutexUniqueLock _l(sTrackingLock);
-    sLimitCallback = cb;
+    sLimitCallback = std::move(cbl);
+    sWarningCallback = std::move(cbw);
 }
 
-void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
+void BpBinder::setBinderProxyCountWatermarks(int high, int low, int warning) {
     RpcMutexUniqueLock _l(sTrackingLock);
     sBinderProxyCountHighWatermark = high;
     sBinderProxyCountLowWatermark = low;
+    sBinderProxyCountWarningWatermark = warning;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 89a4d27..9f03907 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -35,7 +35,8 @@
 }
 class ProcessState;
 
-using binder_proxy_limit_callback = void(*)(int);
+using binder_proxy_limit_callback = std::function<void(int)>;
+using binder_proxy_warning_callback = std::function<void(int)>;
 
 class BpBinder : public IBinder
 {
@@ -86,8 +87,9 @@
     static void         enableCountByUid();
     static void         disableCountByUid();
     static void         setCountByUidEnabled(bool enable);
-    static void         setLimitCallback(binder_proxy_limit_callback cb);
-    static void         setBinderProxyCountWatermarks(int high, int low);
+    static void         setBinderProxyCountEventCallback(binder_proxy_limit_callback cbl,
+                                                         binder_proxy_warning_callback cbw);
+    static void         setBinderProxyCountWatermarks(int high, int low, int warning);
     static uint32_t     getBinderProxyCount();
 
     std::optional<int32_t> getDebugBinderHandle() const;
@@ -212,6 +214,8 @@
     static std::unordered_map<int32_t,uint32_t> sLastLimitCallbackMap;
     static std::atomic<uint32_t>                sBinderProxyCount;
     static std::atomic<uint32_t>                sBinderProxyCountWarned;
+    static binder_proxy_warning_callback        sWarningCallback;
+    static uint32_t                             sBinderProxyCountWarningWatermark;
 };
 
 } // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index ccf3ce8..2a8a353 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -40,6 +40,7 @@
 
     llndk: {
         symbol_file: "libbinder_ndk.map.txt",
+        export_llndk_headers: ["libvendorsupport_llndk_headers"],
     },
 
     export_include_dirs: [
@@ -49,6 +50,7 @@
     ],
 
     cflags: [
+        "-DBINDER_WITH_KERNEL_IPC",
         "-Wall",
         "-Wextra",
         "-Werror",
@@ -79,9 +81,11 @@
     ],
 
     header_libs: [
+        "libvendorsupport_llndk_headers",
         "jni_headers",
     ],
     export_header_lib_headers: [
+        "libvendorsupport_llndk_headers",
         "jni_headers",
     ],
 
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index bf7a0ba..e6d4f46 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -24,6 +24,7 @@
 #include <private/android_filesystem_config.h>
 #endif
 
+#include "../BuildFlags.h"
 #include "ibinder_internal.h"
 #include "parcel_internal.h"
 #include "status_internal.h"
@@ -211,6 +212,12 @@
         binder_status_t status = getClass()->onTransact(this, code, &in, &out);
         return PruneStatusT(status);
     } else if (code == SHELL_COMMAND_TRANSACTION && getClass()->handleShellCommand != nullptr) {
+        if constexpr (!android::kEnableKernelIpc) {
+            // Non-IPC builds do not have getCallingUid(),
+            // so we have no way of authenticating the caller
+            return STATUS_PERMISSION_DENIED;
+        }
+
         int in = data.readFileDescriptor();
         int out = data.readFileDescriptor();
         int err = data.readFileDescriptor();
diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
index 864ff50..d570eab 100644
--- a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
+++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
@@ -22,6 +22,19 @@
 #include <set>
 #include <sstream>
 
+// Include llndk-versioning.h only for vendor build as it is not available for NDK headers.
+#if defined(__ANDROID_VENDOR__)
+#include <android/llndk-versioning.h>
+#else  // __ANDROID_VENDOR__
+#if defined(API_LEVEL_AT_LEAST)
+// Redefine API_LEVEL_AT_LEAST here to replace the version to __ANDROID_API_FUTURE__ as a workaround
+#undef API_LEVEL_AT_LEAST
+#endif
+// TODO(b/322384429) switch this __ANDROID_API_FUTURE__ to sdk_api_level when V is finalized
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
+    (__builtin_available(android __ANDROID_API_FUTURE__, *))
+#endif  // __ANDROID_VENDOR__
+
 namespace aidl::android::os {
 
 /**
@@ -32,7 +45,7 @@
 class PersistableBundle {
    public:
     PersistableBundle() noexcept {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             mPBundle = APersistableBundle_new();
         }
     }
@@ -42,13 +55,13 @@
     PersistableBundle(PersistableBundle&& other) noexcept : mPBundle(other.release()) {}
     // duplicates, does not take ownership of the APersistableBundle*
     PersistableBundle(const PersistableBundle& other) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             mPBundle = APersistableBundle_dup(other.mPBundle);
         }
     }
     // duplicates, does not take ownership of the APersistableBundle*
     PersistableBundle& operator=(const PersistableBundle& other) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             mPBundle = APersistableBundle_dup(other.mPBundle);
         }
         return *this;
@@ -58,7 +71,7 @@
 
     binder_status_t readFromParcel(const AParcel* _Nonnull parcel) {
         reset();
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_readFromParcel(parcel, &mPBundle);
         } else {
             return STATUS_INVALID_OPERATION;
@@ -69,7 +82,7 @@
         if (!mPBundle) {
             return STATUS_BAD_VALUE;
         }
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_writeToParcel(mPBundle, parcel);
         } else {
             return STATUS_INVALID_OPERATION;
@@ -84,7 +97,7 @@
      */
     void reset(APersistableBundle* _Nullable pBundle = nullptr) noexcept {
         if (mPBundle) {
-            if (__builtin_available(android __ANDROID_API_V__, *)) {
+            if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
                 APersistableBundle_delete(mPBundle);
             }
             mPBundle = nullptr;
@@ -97,7 +110,7 @@
      * what should be used to check for equality.
      */
     bool deepEquals(const PersistableBundle& rhs) const {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_isEqual(get(), rhs.get());
         } else {
             return false;
@@ -136,7 +149,7 @@
     inline std::string toString() const {
         if (!mPBundle) {
             return "<PersistableBundle: null>";
-        } else if (__builtin_available(android __ANDROID_API_V__, *)) {
+        } else if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             std::ostringstream os;
             os << "<PersistableBundle: ";
             os << "size: " << std::to_string(APersistableBundle_size(mPBundle));
@@ -147,7 +160,7 @@
     }
 
     int32_t size() const {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_size(mPBundle);
         } else {
             return 0;
@@ -155,7 +168,7 @@
     }
 
     int32_t erase(const std::string& key) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_erase(mPBundle, key.c_str());
         } else {
             return 0;
@@ -163,37 +176,37 @@
     }
 
     void putBoolean(const std::string& key, bool val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putBoolean(mPBundle, key.c_str(), val);
         }
     }
 
     void putInt(const std::string& key, int32_t val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putInt(mPBundle, key.c_str(), val);
         }
     }
 
     void putLong(const std::string& key, int64_t val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putLong(mPBundle, key.c_str(), val);
         }
     }
 
     void putDouble(const std::string& key, double val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putDouble(mPBundle, key.c_str(), val);
         }
     }
 
     void putString(const std::string& key, const std::string& val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putString(mPBundle, key.c_str(), val.c_str());
         }
     }
 
     void putBooleanVector(const std::string& key, const std::vector<bool>& vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             // std::vector<bool> has no ::data().
             int32_t num = vec.size();
             if (num > 0) {
@@ -210,7 +223,7 @@
     }
 
     void putIntVector(const std::string& key, const std::vector<int32_t>& vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t num = vec.size();
             if (num > 0) {
                 APersistableBundle_putIntVector(mPBundle, key.c_str(), vec.data(), num);
@@ -218,7 +231,7 @@
         }
     }
     void putLongVector(const std::string& key, const std::vector<int64_t>& vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t num = vec.size();
             if (num > 0) {
                 APersistableBundle_putLongVector(mPBundle, key.c_str(), vec.data(), num);
@@ -226,7 +239,7 @@
         }
     }
     void putDoubleVector(const std::string& key, const std::vector<double>& vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t num = vec.size();
             if (num > 0) {
                 APersistableBundle_putDoubleVector(mPBundle, key.c_str(), vec.data(), num);
@@ -234,7 +247,7 @@
         }
     }
     void putStringVector(const std::string& key, const std::vector<std::string>& vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t num = vec.size();
             if (num > 0) {
                 char** inVec = (char**)malloc(num * sizeof(char*));
@@ -249,13 +262,13 @@
         }
     }
     void putPersistableBundle(const std::string& key, const PersistableBundle& pBundle) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle_putPersistableBundle(mPBundle, key.c_str(), pBundle.mPBundle);
         }
     }
 
     bool getBoolean(const std::string& key, bool* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_getBoolean(mPBundle, key.c_str(), val);
         } else {
             return false;
@@ -263,7 +276,7 @@
     }
 
     bool getInt(const std::string& key, int32_t* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_getInt(mPBundle, key.c_str(), val);
         } else {
             return false;
@@ -271,7 +284,7 @@
     }
 
     bool getLong(const std::string& key, int64_t* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_getLong(mPBundle, key.c_str(), val);
         } else {
             return false;
@@ -279,7 +292,7 @@
     }
 
     bool getDouble(const std::string& key, double* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return APersistableBundle_getDouble(mPBundle, key.c_str(), val);
         } else {
             return false;
@@ -291,7 +304,7 @@
     }
 
     bool getString(const std::string& key, std::string* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             char* outString = nullptr;
             bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString,
                                                     &stringAllocator, nullptr);
@@ -309,7 +322,7 @@
                                                    const char* _Nonnull, T* _Nullable, int32_t),
                         const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
                         std::vector<T>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t bytes = 0;
             // call first with nullptr to get required size in bytes
             bytes = getVec(pBundle, key, nullptr, 0);
@@ -331,28 +344,28 @@
     }
 
     bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getVecInternal<bool>(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(),
                                         vec);
         }
         return false;
     }
     bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getVecInternal<int32_t>(&APersistableBundle_getIntVector, mPBundle, key.c_str(),
                                            vec);
         }
         return false;
     }
     bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getVecInternal<int64_t>(&APersistableBundle_getLongVector, mPBundle, key.c_str(),
                                            vec);
         }
         return false;
     }
     bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getVecInternal<double>(&APersistableBundle_getDoubleVector, mPBundle,
                                           key.c_str(), vec);
         }
@@ -377,7 +390,7 @@
     }
 
     bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0,
                                                                &stringAllocator, nullptr);
             if (bytes > 0) {
@@ -394,7 +407,7 @@
     }
 
     bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             APersistableBundle* bundle = nullptr;
             bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle);
             if (ret) {
@@ -426,77 +439,77 @@
     }
 
     std::set<std::string> getBooleanKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getBooleanKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getIntKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getIntKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getLongKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getLongKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getDoubleKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getDoubleKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getStringKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getStringKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getBooleanVectorKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getIntVectorKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getLongVectorKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getDoubleVectorKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getStringVectorKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle);
         } else {
             return {};
         }
     }
     std::set<std::string> getPersistableBundleKeys() {
-        if (__builtin_available(android __ANDROID_API_V__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
             return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle);
         } else {
             return {};
diff --git a/libs/binder/ndk/include_ndk/android/persistable_bundle.h b/libs/binder/ndk/include_ndk/android/persistable_bundle.h
index 98c0cb2..42ae15a 100644
--- a/libs/binder/ndk/include_ndk/android/persistable_bundle.h
+++ b/libs/binder/ndk/include_ndk/android/persistable_bundle.h
@@ -17,6 +17,13 @@
 #pragma once
 
 #include <android/binder_parcel.h>
+#if defined(__ANDROID_VENDOR__)
+#include <android/llndk-versioning.h>
+#else
+#if !defined(__INTRODUCED_IN_LLNDK)
+#define __INTRODUCED_IN_LLNDK(level) __attribute__((annotate("introduced_in_llndk=" #level)))
+#endif
+#endif  // __ANDROID_VENDOR__
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/cdefs.h>
@@ -67,25 +74,26 @@
 /**
  * Create a new APersistableBundle.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \return Pointer to a new APersistableBundle
  */
-APersistableBundle* _Nullable APersistableBundle_new() __INTRODUCED_IN(__ANDROID_API_V__);
+APersistableBundle* _Nullable APersistableBundle_new() __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Create a new APersistableBundle based off an existing APersistableBundle.
  * This is a deep copy, so the new APersistableBundle has its own values from
  * copying the original underlying PersistableBundle.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to duplicate
  *
  * \return Pointer to a new APersistableBundle
  */
 APersistableBundle* _Nullable APersistableBundle_dup(const APersistableBundle* _Nonnull pBundle)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Delete an APersistableBundle. This must always be called when finished using
@@ -93,15 +101,15 @@
  *
  * \param pBundle to delete. No-op if null.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_delete(APersistableBundle* _Nullable pBundle)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Check for equality of APersistableBundles.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param lhs bundle to compare against the other param
  * \param rhs bundle to compare against the other param
@@ -110,12 +118,12 @@
  */
 bool APersistableBundle_isEqual(const APersistableBundle* _Nonnull lhs,
                                 const APersistableBundle* _Nonnull rhs)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Read an APersistableBundle from an AParcel.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param parcel to read from
  * \param outPBundle bundle to write to
@@ -129,12 +137,12 @@
  */
 binder_status_t APersistableBundle_readFromParcel(
         const AParcel* _Nonnull parcel, APersistableBundle* _Nullable* _Nonnull outPBundle)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Write an APersistableBundle to an AParcel.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle bundle to write to the parcel
  * \param parcel to write to
@@ -149,25 +157,25 @@
  */
 binder_status_t APersistableBundle_writeToParcel(const APersistableBundle* _Nonnull pBundle,
                                                  AParcel* _Nonnull parcel)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get the size of an APersistableBundle. This is the number of mappings in the
  * object.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to get the size of (number of mappings)
  *
  * \return number of mappings in the object
  */
 int32_t APersistableBundle_size(const APersistableBundle* _Nonnull pBundle)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Erase any entries added with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8 to erase
@@ -175,7 +183,7 @@
  * \return number of entries erased. Either 0 or 1.
  */
 int32_t APersistableBundle_erase(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a boolean associated with the provided key.
@@ -185,10 +193,11 @@
  * \param key for the mapping in UTF-8
  * \param value to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putBoolean(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                                   bool val) __INTRODUCED_IN(__ANDROID_API_V__);
+                                   bool val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put an int32_t associated with the provided key.
@@ -198,10 +207,11 @@
  * \param key for the mapping in UTF-8
  * \param val value to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putInt(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                               int32_t val) __INTRODUCED_IN(__ANDROID_API_V__);
+                               int32_t val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put an int64_t associated with the provided key.
@@ -211,10 +221,11 @@
  * \param key for the mapping in UTF-8
  * \param val value to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putLong(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                                int64_t val) __INTRODUCED_IN(__ANDROID_API_V__);
+                                int64_t val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a double associated with the provided key.
@@ -224,10 +235,11 @@
  * \param key for the mapping in UTF-8
  * \param val value to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putDouble(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                                  double val) __INTRODUCED_IN(__ANDROID_API_V__);
+                                  double val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a string associated with the provided key.
@@ -238,10 +250,11 @@
  * \param key for the mapping in UTF-8
  * \param vec vector to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putString(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                                  const char* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__);
+                                  const char* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a boolean vector associated with the provided key.
@@ -253,11 +266,12 @@
  * \param vec vector to put for the mapping
  * \param num number of elements in the vector
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putBooleanVector(APersistableBundle* _Nonnull pBundle,
                                          const char* _Nonnull key, const bool* _Nonnull vec,
-                                         int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
+                                         int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put an int32_t vector associated with the provided key.
@@ -269,11 +283,11 @@
  * \param vec vector to put for the mapping
  * \param num number of elements in the vector
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putIntVector(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
                                      const int32_t* _Nonnull vec, int32_t num)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put an int64_t vector associated with the provided key.
@@ -285,11 +299,12 @@
  * \param vec vector to put for the mapping
  * \param num number of elements in the vector
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putLongVector(APersistableBundle* _Nonnull pBundle,
                                       const char* _Nonnull key, const int64_t* _Nonnull vec,
-                                      int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
+                                      int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a double vector associated with the provided key.
@@ -301,11 +316,12 @@
  * \param vec vector to put for the mapping
  * \param num number of elements in the vector
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putDoubleVector(APersistableBundle* _Nonnull pBundle,
                                         const char* _Nonnull key, const double* _Nonnull vec,
-                                        int32_t num) __INTRODUCED_IN(__ANDROID_API_V__);
+                                        int32_t num) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put a string vector associated with the provided key.
@@ -317,12 +333,12 @@
  * \param vec vector to put for the mapping
  * \param num number of elements in the vector
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putStringVector(APersistableBundle* _Nonnull pBundle,
                                         const char* _Nonnull key,
                                         const char* _Nullable const* _Nullable vec, int32_t num)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Put an APersistableBundle associated with the provided key.
@@ -333,17 +349,17 @@
  * \param key for the mapping in UTF-8
  * \param val value to put for the mapping
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  */
 void APersistableBundle_putPersistableBundle(APersistableBundle* _Nonnull pBundle,
                                              const char* _Nonnull key,
                                              const APersistableBundle* _Nonnull val)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a boolean associated with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -353,12 +369,12 @@
  */
 bool APersistableBundle_getBoolean(const APersistableBundle* _Nonnull pBundle,
                                    const char* _Nonnull key, bool* _Nonnull val)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get an int32_t associated with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -367,12 +383,13 @@
  * \return true if a value exists for the provided key
  */
 bool APersistableBundle_getInt(const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
-                               int32_t* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__);
+                               int32_t* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get an int64_t associated with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -382,12 +399,12 @@
  */
 bool APersistableBundle_getLong(const APersistableBundle* _Nonnull pBundle,
                                 const char* _Nonnull key, int64_t* _Nonnull val)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a double associated with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -397,13 +414,13 @@
  */
 bool APersistableBundle_getDouble(const APersistableBundle* _Nonnull pBundle,
                                   const char* _Nonnull key, double* _Nonnull val)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a string associated with the provided key.
  * The caller is responsible for freeing the returned data.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -418,7 +435,8 @@
 int32_t APersistableBundle_getString(const APersistableBundle* _Nonnull pBundle,
                                      const char* _Nonnull key, char* _Nullable* _Nonnull val,
                                      APersistableBundle_stringAllocator stringAllocator,
-                                     void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
+                                     void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a boolean vector associated with the provided key and place it in the
@@ -445,7 +463,7 @@
 int32_t APersistableBundle_getBooleanVector(const APersistableBundle* _Nonnull pBundle,
                                             const char* _Nonnull key, bool* _Nullable buffer,
                                             int32_t bufferSizeBytes)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get an int32_t vector associated with the provided key and place it in the
@@ -471,7 +489,8 @@
  */
 int32_t APersistableBundle_getIntVector(const APersistableBundle* _Nonnull pBundle,
                                         const char* _Nonnull key, int32_t* _Nullable buffer,
-                                        int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__);
+                                        int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get an int64_t vector associated with the provided key and place it in the
@@ -497,8 +516,8 @@
  */
 int32_t APersistableBundle_getLongVector(const APersistableBundle* _Nonnull pBundle,
                                          const char* _Nonnull key, int64_t* _Nullable buffer,
-                                         int32_t bufferSizeBytes)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+                                         int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a double vector associated with the provided key and place it in the
@@ -525,7 +544,7 @@
 int32_t APersistableBundle_getDoubleVector(const APersistableBundle* _Nonnull pBundle,
                                            const char* _Nonnull key, double* _Nullable buffer,
                                            int32_t bufferSizeBytes)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get a string vector associated with the provided key and place it in the
@@ -562,12 +581,12 @@
                                            int32_t bufferSizeBytes,
                                            APersistableBundle_stringAllocator stringAllocator,
                                            void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get an APersistableBundle* associated with the provided key.
  *
- * Available since API level __ANDROID_API_V__.
+ * Available since API level 202404.
  *
  * \param pBundle to operate on
  * \param key for the mapping in UTF-8
@@ -581,7 +600,7 @@
 bool APersistableBundle_getPersistableBundle(const APersistableBundle* _Nonnull pBundle,
                                              const char* _Nonnull key,
                                              APersistableBundle* _Nullable* _Nonnull outBundle)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -614,7 +633,7 @@
                                           int32_t bufferSizeBytes,
                                           APersistableBundle_stringAllocator stringAllocator,
                                           void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -645,7 +664,8 @@
 int32_t APersistableBundle_getIntKeys(const APersistableBundle* _Nonnull pBundle,
                                       char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes,
                                       APersistableBundle_stringAllocator stringAllocator,
-                                      void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
+                                      void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -676,7 +696,8 @@
 int32_t APersistableBundle_getLongKeys(const APersistableBundle* _Nonnull pBundle,
                                        char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes,
                                        APersistableBundle_stringAllocator stringAllocator,
-                                       void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
+                                       void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -708,8 +729,8 @@
                                          char* _Nullable* _Nullable outKeys,
                                          int32_t bufferSizeBytes,
                                          APersistableBundle_stringAllocator stringAllocator,
-                                         void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+                                         void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -741,8 +762,8 @@
                                          char* _Nullable* _Nullable outKeys,
                                          int32_t bufferSizeBytes,
                                          APersistableBundle_stringAllocator stringAllocator,
-                                         void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+                                         void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -775,7 +796,7 @@
                                                 int32_t bufferSizeBytes,
                                                 APersistableBundle_stringAllocator stringAllocator,
                                                 void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -808,7 +829,7 @@
                                             int32_t bufferSizeBytes,
                                             APersistableBundle_stringAllocator stringAllocator,
                                             void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -841,7 +862,7 @@
                                              int32_t bufferSizeBytes,
                                              APersistableBundle_stringAllocator stringAllocator,
                                              void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -873,7 +894,7 @@
                                                int32_t bufferSizeBytes,
                                                APersistableBundle_stringAllocator stringAllocator,
                                                void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -906,7 +927,7 @@
                                                int32_t bufferSizeBytes,
                                                APersistableBundle_stringAllocator stringAllocator,
                                                void* _Nullable context)
-        __INTRODUCED_IN(__ANDROID_API_V__);
+        __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Get all of the keys associated with this specific type and place it in the
@@ -937,6 +958,6 @@
 int32_t APersistableBundle_getPersistableBundleKeys(
         const APersistableBundle* _Nonnull pBundle, char* _Nullable* _Nullable outKeys,
         int32_t bufferSizeBytes, APersistableBundle_stringAllocator stringAllocator,
-        void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__);
+        void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__) __INTRODUCED_IN_LLNDK(202404);
 
 __END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index a905dff..c665ad8 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -20,6 +20,10 @@
 #include <android/binder_status.h>
 #include <sys/cdefs.h>
 
+#ifndef __TRUSTY__
+#include <android/llndk-versioning.h>
+#endif
+
 __BEGIN_DECLS
 
 enum AServiceManager_AddServiceFlag : uint32_t {
@@ -252,9 +256,8 @@
  * \return the result of dlopen of the specified HAL
  */
 void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
-                                                 int flag)
-        // TODO(b/302113279) use __INTRODUCED_LLNDK for vendor variants
-        __INTRODUCED_IN(__ANDROID_API_V__);
+                                                 int flag) __INTRODUCED_IN(__ANDROID_API_V__)
+        __INTRODUCED_IN_LLNDK(202404);
 
 /**
  * Prevent lazy services without client from shutting down their process
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index de624e4..826e199 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -164,47 +164,88 @@
 LIBBINDER_NDK35 { # introduced=VanillaIceCream
   global:
     APersistableBundle_readFromParcel;
+    APersistableBundle_readFromParcel; # llndk=202404
     APersistableBundle_writeToParcel;
+    APersistableBundle_writeToParcel; # llndk=202404
     APersistableBundle_new;
+    APersistableBundle_new; # llndk=202404
     APersistableBundle_dup;
+    APersistableBundle_dup; # llndk=202404
     APersistableBundle_delete;
+    APersistableBundle_delete; # llndk=202404
     APersistableBundle_isEqual;
+    APersistableBundle_isEqual; # llndk=202404
     APersistableBundle_size;
+    APersistableBundle_size; # llndk=202404
     APersistableBundle_erase;
+    APersistableBundle_erase; # llndk=202404
     APersistableBundle_putBoolean;
+    APersistableBundle_putBoolean; # llndk=202404
     APersistableBundle_putInt;
+    APersistableBundle_putInt; # llndk=202404
     APersistableBundle_putLong;
+    APersistableBundle_putLong; # llndk=202404
     APersistableBundle_putDouble;
+    APersistableBundle_putDouble; # llndk=202404
     APersistableBundle_putString;
+    APersistableBundle_putString; # llndk=202404
     APersistableBundle_putBooleanVector;
+    APersistableBundle_putBooleanVector; # llndk=202404
     APersistableBundle_putIntVector;
+    APersistableBundle_putIntVector; # llndk=202404
     APersistableBundle_putLongVector;
+    APersistableBundle_putLongVector; # llndk=202404
     APersistableBundle_putDoubleVector;
+    APersistableBundle_putDoubleVector; # llndk=202404
     APersistableBundle_putStringVector;
+    APersistableBundle_putStringVector; # llndk=202404
     APersistableBundle_putPersistableBundle;
+    APersistableBundle_putPersistableBundle; # llndk=202404
     APersistableBundle_getBoolean;
+    APersistableBundle_getBoolean; # llndk=202404
     APersistableBundle_getInt;
+    APersistableBundle_getInt; # llndk=202404
     APersistableBundle_getLong;
+    APersistableBundle_getLong; # llndk=202404
     APersistableBundle_getDouble;
+    APersistableBundle_getDouble; # llndk=202404
     APersistableBundle_getString;
+    APersistableBundle_getString; # llndk=202404
     APersistableBundle_getBooleanVector;
+    APersistableBundle_getBooleanVector; # llndk=202404
     APersistableBundle_getIntVector;
+    APersistableBundle_getIntVector; # llndk=202404
     APersistableBundle_getLongVector;
+    APersistableBundle_getLongVector; # llndk=202404
     APersistableBundle_getDoubleVector;
+    APersistableBundle_getDoubleVector; # llndk=202404
     APersistableBundle_getStringVector;
+    APersistableBundle_getStringVector; # llndk=202404
     APersistableBundle_getPersistableBundle;
+    APersistableBundle_getPersistableBundle; # llndk=202404
     APersistableBundle_getBooleanKeys;
+    APersistableBundle_getBooleanKeys; # llndk=202404
     APersistableBundle_getIntKeys;
+    APersistableBundle_getIntKeys; # llndk=202404
     APersistableBundle_getLongKeys;
+    APersistableBundle_getLongKeys; # llndk=202404
     APersistableBundle_getDoubleKeys;
+    APersistableBundle_getDoubleKeys; # llndk=202404
     APersistableBundle_getStringKeys;
+    APersistableBundle_getStringKeys; # llndk=202404
     APersistableBundle_getBooleanVectorKeys;
+    APersistableBundle_getBooleanVectorKeys; # llndk=202404
     APersistableBundle_getIntVectorKeys;
+    APersistableBundle_getIntVectorKeys; # llndk=202404
     APersistableBundle_getLongVectorKeys;
+    APersistableBundle_getLongVectorKeys; # llndk=202404
     APersistableBundle_getDoubleVectorKeys;
+    APersistableBundle_getDoubleVectorKeys; # llndk=202404
     APersistableBundle_getStringVectorKeys;
+    APersistableBundle_getStringVectorKeys; # llndk=202404
     APersistableBundle_getPersistableBundleKeys;
-    AServiceManager_openDeclaredPassthroughHal; # systemapi llndk
+    APersistableBundle_getPersistableBundleKeys; # llndk=202404
+    AServiceManager_openDeclaredPassthroughHal; # systemapi llndk=202404
 };
 
 LIBBINDER_NDK_PLATFORM {
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
index ca3d5e6..39cf1c4 100644
--- a/libs/binder/ndk/stability.cpp
+++ b/libs/binder/ndk/stability.cpp
@@ -23,7 +23,7 @@
 
 using ::android::internal::Stability;
 
-#ifdef __ANDROID_VNDK__
+#if defined(__ANDROID_VNDK__) && !defined(__TRUSTY__)
 #error libbinder_ndk should only be built in a system context
 #endif
 
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 16049f2..0540ed3 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -101,6 +101,8 @@
 mod parcel;
 mod proxy;
 #[cfg(not(target_os = "trusty"))]
+mod service;
+#[cfg(not(target_os = "trusty"))]
 mod state;
 
 use binder_ndk_sys as sys;
@@ -108,14 +110,13 @@
 pub use crate::binder_async::{BinderAsyncPool, BoxFuture};
 pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
 pub use error::{ExceptionCode, IntoBinderResult, Status, StatusCode};
-pub use native::{
-    add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service,
-    LazyServiceGuard,
-};
 pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
-pub use proxy::{
-    get_declared_instances, get_interface, get_service, is_declared, wait_for_interface,
-    wait_for_service, DeathRecipient, SpIBinder, WpIBinder,
+pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
+#[cfg(not(target_os = "trusty"))]
+pub use service::{
+    add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service,
+    is_declared, is_handling_transaction, register_lazy_service, wait_for_interface,
+    wait_for_service, LazyServiceGuard,
 };
 #[cfg(not(target_os = "trusty"))]
 pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 8ae010e..da9d7dc 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -23,12 +23,11 @@
 use crate::sys;
 
 use std::convert::TryFrom;
-use std::ffi::{c_void, CStr, CString};
+use std::ffi::{c_void, CStr};
 use std::io::Write;
 use std::mem::ManuallyDrop;
 use std::ops::Deref;
 use std::os::raw::c_char;
-use std::sync::Mutex;
 
 /// Rust wrapper around Binder remotable objects.
 ///
@@ -462,110 +461,6 @@
     }
 }
 
-/// Register a new service with the default service manager.
-///
-/// Registers the given binder object with the given identifier. If successful,
-/// this service can then be retrieved using that identifier.
-///
-/// This function will panic if the identifier contains a 0 byte (NUL).
-pub fn add_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
-    let instance = CString::new(identifier).unwrap();
-    let status =
-    // Safety: `AServiceManager_addService` expects valid `AIBinder` and C
-    // string pointers. Caller retains ownership of both pointers.
-    // `AServiceManager_addService` creates a new strong reference and copies
-    // the string, so both pointers need only be valid until the call returns.
-        unsafe { sys::AServiceManager_addService(binder.as_native_mut(), instance.as_ptr()) };
-    status_result(status)
-}
-
-/// Register a dynamic service via the LazyServiceRegistrar.
-///
-/// Registers the given binder object with the given identifier. If successful,
-/// this service can then be retrieved using that identifier. The service process
-/// will be shut down once all registered services are no longer in use.
-///
-/// If any service in the process is registered as lazy, all should be, otherwise
-/// the process may be shut down while a service is in use.
-///
-/// This function will panic if the identifier contains a 0 byte (NUL).
-pub fn register_lazy_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
-    let instance = CString::new(identifier).unwrap();
-    // Safety: `AServiceManager_registerLazyService` expects valid `AIBinder` and C
-    // string pointers. Caller retains ownership of both
-    // pointers. `AServiceManager_registerLazyService` creates a new strong reference
-    // and copies the string, so both pointers need only be valid until the
-    // call returns.
-    let status = unsafe {
-        sys::AServiceManager_registerLazyService(binder.as_native_mut(), instance.as_ptr())
-    };
-    status_result(status)
-}
-
-/// Prevent a process which registers lazy services from being shut down even when none
-/// of the services is in use.
-///
-/// If persist is true then shut down will be blocked until this function is called again with
-/// persist false. If this is to be the initial state, call this function before calling
-/// register_lazy_service.
-///
-/// Consider using [`LazyServiceGuard`] rather than calling this directly.
-pub fn force_lazy_services_persist(persist: bool) {
-    // Safety: No borrowing or transfer of ownership occurs here.
-    unsafe { sys::AServiceManager_forceLazyServicesPersist(persist) }
-}
-
-/// An RAII object to ensure a process which registers lazy services is not killed. During the
-/// lifetime of any of these objects the service manager will not not kill the process even if none
-/// of its lazy services are in use.
-#[must_use]
-#[derive(Debug)]
-pub struct LazyServiceGuard {
-    // Prevent construction outside this module.
-    _private: (),
-}
-
-// Count of how many LazyServiceGuard objects are in existence.
-static GUARD_COUNT: Mutex<u64> = Mutex::new(0);
-
-impl LazyServiceGuard {
-    /// Create a new LazyServiceGuard to prevent the service manager prematurely killing this
-    /// process.
-    pub fn new() -> Self {
-        let mut count = GUARD_COUNT.lock().unwrap();
-        *count += 1;
-        if *count == 1 {
-            // It's important that we make this call with the mutex held, to make sure
-            // that multiple calls (e.g. if the count goes 1 -> 0 -> 1) are correctly
-            // sequenced. (That also means we can't just use an AtomicU64.)
-            force_lazy_services_persist(true);
-        }
-        Self { _private: () }
-    }
-}
-
-impl Drop for LazyServiceGuard {
-    fn drop(&mut self) {
-        let mut count = GUARD_COUNT.lock().unwrap();
-        *count -= 1;
-        if *count == 0 {
-            force_lazy_services_persist(false);
-        }
-    }
-}
-
-impl Clone for LazyServiceGuard {
-    fn clone(&self) -> Self {
-        Self::new()
-    }
-}
-
-impl Default for LazyServiceGuard {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 /// Tests often create a base BBinder instance; so allowing the unit
 /// type to be remotable translates nicely to Binder::new(()).
 impl Remotable for () {
@@ -590,10 +485,3 @@
 }
 
 impl Interface for () {}
-
-/// Determine whether the current thread is currently executing an incoming
-/// transaction.
-pub fn is_handling_transaction() -> bool {
-    // Safety: This method is always safe to call.
-    unsafe { sys::AIBinder_isHandlingTransaction() }
-}
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 7434e9d..340014a 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -29,11 +29,10 @@
 
 use std::cmp::Ordering;
 use std::convert::TryInto;
-use std::ffi::{c_void, CStr, CString};
+use std::ffi::{c_void, CString};
 use std::fmt;
 use std::mem;
 use std::os::fd::AsRawFd;
-use std::os::raw::c_char;
 use std::ptr;
 use std::sync::Arc;
 
@@ -129,14 +128,6 @@
     }
 }
 
-fn interface_cast<T: FromIBinder + ?Sized>(service: Option<SpIBinder>) -> Result<Strong<T>> {
-    if let Some(service) = service {
-        FromIBinder::try_from(service)
-    } else {
-        Err(StatusCode::NAME_NOT_FOUND)
-    }
-}
-
 pub mod unstable_api {
     use super::{sys, SpIBinder};
 
@@ -739,93 +730,6 @@
     }
 }
 
-/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
-/// exist.
-pub fn get_service(name: &str) -> Option<SpIBinder> {
-    let name = CString::new(name).ok()?;
-    // Safety: `AServiceManager_getService` returns either a null pointer or a
-    // valid pointer to an owned `AIBinder`. Either of these values is safe to
-    // pass to `SpIBinder::from_raw`.
-    unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) }
-}
-
-/// Retrieve an existing service, or start it if it is configured as a dynamic
-/// service and isn't yet started.
-pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
-    let name = CString::new(name).ok()?;
-    // Safety: `AServiceManager_waitforService` returns either a null pointer or
-    // a valid pointer to an owned `AIBinder`. Either of these values is safe to
-    // pass to `SpIBinder::from_raw`.
-    unsafe { SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr())) }
-}
-
-/// Retrieve an existing service for a particular interface, blocking for a few
-/// seconds if it doesn't yet exist.
-pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
-    interface_cast(get_service(name))
-}
-
-/// Retrieve an existing service for a particular interface, or start it if it
-/// is configured as a dynamic service and isn't yet started.
-pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
-    interface_cast(wait_for_service(name))
-}
-
-/// Check if a service is declared (e.g. in a VINTF manifest)
-pub fn is_declared(interface: &str) -> Result<bool> {
-    let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
-
-    // Safety: `interface` is a valid null-terminated C-style string and is only
-    // borrowed for the lifetime of the call. The `interface` local outlives
-    // this call as it lives for the function scope.
-    unsafe { Ok(sys::AServiceManager_isDeclared(interface.as_ptr())) }
-}
-
-/// Retrieve all declared instances for a particular interface
-///
-/// For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo'
-/// is passed here, then ["foo"] would be returned.
-pub fn get_declared_instances(interface: &str) -> Result<Vec<String>> {
-    unsafe extern "C" fn callback(instance: *const c_char, opaque: *mut c_void) {
-        // Safety: opaque was a mutable pointer created below from a Vec of
-        // CString, and outlives this callback. The null handling here is just
-        // to avoid the possibility of unwinding across C code if this crate is
-        // ever compiled with panic=unwind.
-        if let Some(instances) = unsafe { opaque.cast::<Vec<CString>>().as_mut() } {
-            // Safety: instance is a valid null-terminated C string with a
-            // lifetime at least as long as this function, and we immediately
-            // copy it into an owned CString.
-            unsafe {
-                instances.push(CStr::from_ptr(instance).to_owned());
-            }
-        } else {
-            eprintln!("Opaque pointer was null in get_declared_instances callback!");
-        }
-    }
-
-    let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
-    let mut instances: Vec<CString> = vec![];
-    // Safety: `interface` and `instances` are borrowed for the length of this
-    // call and both outlive the call. `interface` is guaranteed to be a valid
-    // null-terminated C-style string.
-    unsafe {
-        sys::AServiceManager_forEachDeclaredInstance(
-            interface.as_ptr(),
-            &mut instances as *mut _ as *mut c_void,
-            Some(callback),
-        );
-    }
-
-    instances
-        .into_iter()
-        .map(CString::into_string)
-        .collect::<std::result::Result<Vec<String>, _>>()
-        .map_err(|e| {
-            eprintln!("An interface instance name was not a valid UTF-8 string: {}", e);
-            StatusCode::BAD_VALUE
-        })
-}
-
 /// Safety: `SpIBinder` guarantees that `binder` always contains a valid pointer
 /// to an `AIBinder`, so we can trivially extract this pointer here.
 unsafe impl AsNative<sys::AIBinder> for SpIBinder {
diff --git a/libs/binder/rust/src/service.rs b/libs/binder/rust/src/service.rs
new file mode 100644
index 0000000..3ca3b54
--- /dev/null
+++ b/libs/binder/rust/src/service.rs
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+use crate::binder::{AsNative, FromIBinder, Strong};
+use crate::error::{status_result, Result, StatusCode};
+use crate::proxy::SpIBinder;
+use crate::sys;
+
+use std::ffi::{c_void, CStr, CString};
+use std::os::raw::c_char;
+use std::sync::Mutex;
+
+/// Register a new service with the default service manager.
+///
+/// Registers the given binder object with the given identifier. If successful,
+/// this service can then be retrieved using that identifier.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
+pub fn add_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
+    let instance = CString::new(identifier).unwrap();
+    let status =
+    // Safety: `AServiceManager_addService` expects valid `AIBinder` and C
+    // string pointers. Caller retains ownership of both pointers.
+    // `AServiceManager_addService` creates a new strong reference and copies
+    // the string, so both pointers need only be valid until the call returns.
+        unsafe { sys::AServiceManager_addService(binder.as_native_mut(), instance.as_ptr()) };
+    status_result(status)
+}
+
+/// Register a dynamic service via the LazyServiceRegistrar.
+///
+/// Registers the given binder object with the given identifier. If successful,
+/// this service can then be retrieved using that identifier. The service process
+/// will be shut down once all registered services are no longer in use.
+///
+/// If any service in the process is registered as lazy, all should be, otherwise
+/// the process may be shut down while a service is in use.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
+pub fn register_lazy_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
+    let instance = CString::new(identifier).unwrap();
+    // Safety: `AServiceManager_registerLazyService` expects valid `AIBinder` and C
+    // string pointers. Caller retains ownership of both
+    // pointers. `AServiceManager_registerLazyService` creates a new strong reference
+    // and copies the string, so both pointers need only be valid until the
+    // call returns.
+    let status = unsafe {
+        sys::AServiceManager_registerLazyService(binder.as_native_mut(), instance.as_ptr())
+    };
+    status_result(status)
+}
+
+/// Prevent a process which registers lazy services from being shut down even when none
+/// of the services is in use.
+///
+/// If persist is true then shut down will be blocked until this function is called again with
+/// persist false. If this is to be the initial state, call this function before calling
+/// register_lazy_service.
+///
+/// Consider using [`LazyServiceGuard`] rather than calling this directly.
+pub fn force_lazy_services_persist(persist: bool) {
+    // Safety: No borrowing or transfer of ownership occurs here.
+    unsafe { sys::AServiceManager_forceLazyServicesPersist(persist) }
+}
+
+/// An RAII object to ensure a process which registers lazy services is not killed. During the
+/// lifetime of any of these objects the service manager will not kill the process even if none
+/// of its lazy services are in use.
+#[must_use]
+#[derive(Debug)]
+pub struct LazyServiceGuard {
+    // Prevent construction outside this module.
+    _private: (),
+}
+
+// Count of how many LazyServiceGuard objects are in existence.
+static GUARD_COUNT: Mutex<u64> = Mutex::new(0);
+
+impl LazyServiceGuard {
+    /// Create a new LazyServiceGuard to prevent the service manager prematurely killing this
+    /// process.
+    pub fn new() -> Self {
+        let mut count = GUARD_COUNT.lock().unwrap();
+        *count += 1;
+        if *count == 1 {
+            // It's important that we make this call with the mutex held, to make sure
+            // that multiple calls (e.g. if the count goes 1 -> 0 -> 1) are correctly
+            // sequenced. (That also means we can't just use an AtomicU64.)
+            force_lazy_services_persist(true);
+        }
+        Self { _private: () }
+    }
+}
+
+impl Drop for LazyServiceGuard {
+    fn drop(&mut self) {
+        let mut count = GUARD_COUNT.lock().unwrap();
+        *count -= 1;
+        if *count == 0 {
+            force_lazy_services_persist(false);
+        }
+    }
+}
+
+impl Clone for LazyServiceGuard {
+    fn clone(&self) -> Self {
+        Self::new()
+    }
+}
+
+impl Default for LazyServiceGuard {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+/// Determine whether the current thread is currently executing an incoming
+/// transaction.
+pub fn is_handling_transaction() -> bool {
+    // Safety: This method is always safe to call.
+    unsafe { sys::AIBinder_isHandlingTransaction() }
+}
+
+fn interface_cast<T: FromIBinder + ?Sized>(service: Option<SpIBinder>) -> Result<Strong<T>> {
+    if let Some(service) = service {
+        FromIBinder::try_from(service)
+    } else {
+        Err(StatusCode::NAME_NOT_FOUND)
+    }
+}
+
+/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
+/// exist.
+pub fn get_service(name: &str) -> Option<SpIBinder> {
+    let name = CString::new(name).ok()?;
+    // Safety: `AServiceManager_getService` returns either a null pointer or a
+    // valid pointer to an owned `AIBinder`. Either of these values is safe to
+    // pass to `SpIBinder::from_raw`.
+    unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) }
+}
+
+/// Retrieve an existing service, or start it if it is configured as a dynamic
+/// service and isn't yet started.
+pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
+    let name = CString::new(name).ok()?;
+    // Safety: `AServiceManager_waitforService` returns either a null pointer or
+    // a valid pointer to an owned `AIBinder`. Either of these values is safe to
+    // pass to `SpIBinder::from_raw`.
+    unsafe { SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr())) }
+}
+
+/// Retrieve an existing service for a particular interface, blocking for a few
+/// seconds if it doesn't yet exist.
+pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+    interface_cast(get_service(name))
+}
+
+/// Retrieve an existing service for a particular interface, or start it if it
+/// is configured as a dynamic service and isn't yet started.
+pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+    interface_cast(wait_for_service(name))
+}
+
+/// Check if a service is declared (e.g. in a VINTF manifest)
+pub fn is_declared(interface: &str) -> Result<bool> {
+    let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
+
+    // Safety: `interface` is a valid null-terminated C-style string and is only
+    // borrowed for the lifetime of the call. The `interface` local outlives
+    // this call as it lives for the function scope.
+    unsafe { Ok(sys::AServiceManager_isDeclared(interface.as_ptr())) }
+}
+
+/// Retrieve all declared instances for a particular interface
+///
+/// For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo'
+/// is passed here, then ["foo"] would be returned.
+pub fn get_declared_instances(interface: &str) -> Result<Vec<String>> {
+    unsafe extern "C" fn callback(instance: *const c_char, opaque: *mut c_void) {
+        // Safety: opaque was a mutable pointer created below from a Vec of
+        // CString, and outlives this callback. The null handling here is just
+        // to avoid the possibility of unwinding across C code if this crate is
+        // ever compiled with panic=unwind.
+        if let Some(instances) = unsafe { opaque.cast::<Vec<CString>>().as_mut() } {
+            // Safety: instance is a valid null-terminated C string with a
+            // lifetime at least as long as this function, and we immediately
+            // copy it into an owned CString.
+            unsafe {
+                instances.push(CStr::from_ptr(instance).to_owned());
+            }
+        } else {
+            eprintln!("Opaque pointer was null in get_declared_instances callback!");
+        }
+    }
+
+    let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
+    let mut instances: Vec<CString> = vec![];
+    // Safety: `interface` and `instances` are borrowed for the length of this
+    // call and both outlive the call. `interface` is guaranteed to be a valid
+    // null-terminated C-style string.
+    unsafe {
+        sys::AServiceManager_forEachDeclaredInstance(
+            interface.as_ptr(),
+            &mut instances as *mut _ as *mut c_void,
+            Some(callback),
+        );
+    }
+
+    instances
+        .into_iter()
+        .map(CString::into_string)
+        .collect::<std::result::Result<Vec<String>, _>>()
+        .map_err(|e| {
+            eprintln!("An interface instance name was not a valid UTF-8 string: {}", e);
+            StatusCode::BAD_VALUE
+        })
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 0ee96e7..2cea14f 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -115,6 +115,7 @@
     BINDER_LIB_TEST_GET_SCHEDULING_POLICY,
     BINDER_LIB_TEST_NOP_TRANSACTION_WAIT,
     BINDER_LIB_TEST_GETPID,
+    BINDER_LIB_TEST_GETUID,
     BINDER_LIB_TEST_ECHO_VECTOR,
     BINDER_LIB_TEST_GET_NON_BLOCKING_FD,
     BINDER_LIB_TEST_REJECT_OBJECTS,
@@ -1477,6 +1478,86 @@
     EXPECT_EQ(BpBinder::getBinderProxyCount(), initialCount);
 }
 
+static constexpr int kBpCountHighWatermark = 20;
+static constexpr int kBpCountLowWatermark = 10;
+static constexpr int kBpCountWarningWatermark = 15;
+static constexpr int kInvalidUid = -1;
+
+TEST_F(BinderLibTest, BinderProxyCountCallback) {
+    Parcel data, reply;
+    sp<IBinder> server = addServer();
+    ASSERT_NE(server, nullptr);
+
+    BpBinder::enableCountByUid();
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GETUID, data, &reply), StatusEq(NO_ERROR));
+    int32_t uid = reply.readInt32();
+    ASSERT_NE(uid, kInvalidUid);
+
+    uint32_t initialCount = BpBinder::getBinderProxyCount();
+    {
+        uint32_t count = initialCount;
+        BpBinder::setBinderProxyCountWatermarks(kBpCountHighWatermark,
+                                                kBpCountLowWatermark,
+                                                kBpCountWarningWatermark);
+        int limitCallbackUid = kInvalidUid;
+        int warningCallbackUid = kInvalidUid;
+        BpBinder::setBinderProxyCountEventCallback([&](int uid) { limitCallbackUid = uid; },
+                                                   [&](int uid) { warningCallbackUid = uid; });
+
+        std::vector<sp<IBinder> > proxies;
+        auto createProxyOnce = [&](int expectedWarningCallbackUid, int expectedLimitCallbackUid) {
+            warningCallbackUid = limitCallbackUid = kInvalidUid;
+            ASSERT_THAT(server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply),
+                        StatusEq(NO_ERROR));
+            proxies.push_back(reply.readStrongBinder());
+            EXPECT_EQ(BpBinder::getBinderProxyCount(), ++count);
+            EXPECT_EQ(warningCallbackUid, expectedWarningCallbackUid);
+            EXPECT_EQ(limitCallbackUid, expectedLimitCallbackUid);
+        };
+        auto removeProxyOnce = [&](int expectedWarningCallbackUid, int expectedLimitCallbackUid) {
+            warningCallbackUid = limitCallbackUid = kInvalidUid;
+            proxies.pop_back();
+            EXPECT_EQ(BpBinder::getBinderProxyCount(), --count);
+            EXPECT_EQ(warningCallbackUid, expectedWarningCallbackUid);
+            EXPECT_EQ(limitCallbackUid, expectedLimitCallbackUid);
+        };
+
+        // Test the increment/decrement of the binder proxies.
+        for (int i = 1; i <= kBpCountWarningWatermark; i++) {
+            createProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(uid, kInvalidUid); // Warning callback should have been triggered.
+        for (int i = kBpCountWarningWatermark + 2; i <= kBpCountHighWatermark; i++) {
+            createProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(kInvalidUid, uid); // Limit callback should have been triggered.
+        createProxyOnce(kInvalidUid, kInvalidUid);
+        for (int i = kBpCountHighWatermark + 2; i >= kBpCountHighWatermark; i--) {
+            removeProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(kInvalidUid, kInvalidUid);
+
+        // Go down below the low watermark.
+        for (int i = kBpCountHighWatermark; i >= kBpCountLowWatermark; i--) {
+            removeProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        for (int i = kBpCountLowWatermark; i <= kBpCountWarningWatermark; i++) {
+            createProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(uid, kInvalidUid); // Warning callback should have been triggered.
+        for (int i = kBpCountWarningWatermark + 2; i <= kBpCountHighWatermark; i++) {
+            createProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(kInvalidUid, uid); // Limit callback should have been triggered.
+        createProxyOnce(kInvalidUid, kInvalidUid);
+        for (int i = kBpCountHighWatermark + 2; i >= kBpCountHighWatermark; i--) {
+            removeProxyOnce(kInvalidUid, kInvalidUid);
+        }
+        createProxyOnce(kInvalidUid, kInvalidUid);
+    }
+    EXPECT_EQ(BpBinder::getBinderProxyCount(), initialCount);
+}
+
 class BinderLibRpcTestBase : public BinderLibTest {
 public:
     void SetUp() override {
@@ -1680,6 +1761,9 @@
             case BINDER_LIB_TEST_GETPID:
                 reply->writeInt32(getpid());
                 return NO_ERROR;
+            case BINDER_LIB_TEST_GETUID:
+                reply->writeInt32(getuid());
+                return NO_ERROR;
             case BINDER_LIB_TEST_NOP_TRANSACTION_WAIT:
                 usleep(5000);
                 [[fallthrough]];
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 62fe9e5..8832f1a 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -74,6 +74,12 @@
 }
 
 static inline bool hasExperimentalRpc() {
+#ifdef BINDER_RPC_TO_TRUSTY_TEST
+    // Trusty services do not support the experimental version,
+    // so that we can update the prebuilts separately.
+    // This covers the binderRpcToTrustyTest case on Android.
+    return false;
+#endif
 #ifdef __ANDROID__
     return base::GetProperty("ro.build.version.codename", "") != "REL";
 #else
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index 885bb45..f480780 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -48,11 +48,13 @@
     EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 15));
 }
 
+#ifndef BINDER_RPC_TO_TRUSTY_TEST
 TEST(BinderRpc, CanUseExperimentalWireVersion) {
     auto session = RpcSession::make();
     EXPECT_EQ(hasExperimentalRpc(),
               session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL));
 }
+#endif
 
 TEST_P(BinderRpc, Ping) {
     auto proc = createRpcTestSocketServerProcess({});
diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
index 0a584bf..83d0ca7 100644
--- a/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
+++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
@@ -95,14 +95,16 @@
                  },
                  [](FuzzedDataProvider*, const sp<BpBinder>& bpbinder,
                     const sp<IBinder::DeathRecipient>&) -> void {
-                     binder_proxy_limit_callback cb = binder_proxy_limit_callback();
-                     bpbinder->setLimitCallback(cb);
+                     binder_proxy_limit_callback cbl = binder_proxy_limit_callback();
+                     binder_proxy_warning_callback cbw = binder_proxy_warning_callback();
+                     bpbinder->setBinderProxyCountEventCallback(cbl, cbw);
                  },
                  [](FuzzedDataProvider* fdp, const sp<BpBinder>& bpbinder,
                     const sp<IBinder::DeathRecipient>&) -> void {
                      int high = fdp->ConsumeIntegral<int>();
                      int low = fdp->ConsumeIntegral<int>();
-                     bpbinder->setBinderProxyCountWatermarks(high, low);
+                     int warning = fdp->ConsumeIntegral<int>();
+                     bpbinder->setBinderProxyCountWatermarks(high, low, warning);
                  }};
 
 } // namespace android
diff --git a/libs/binder/trusty/build-config-usertests b/libs/binder/trusty/build-config-usertests
index d0a1fbc..72e5ff9 100644
--- a/libs/binder/trusty/build-config-usertests
+++ b/libs/binder/trusty/build-config-usertests
@@ -16,4 +16,5 @@
 
 [
     porttest("com.android.trusty.binderRpcTest"),
+    porttest("com.android.trusty.rust.binder_rpc_test.test"),
 ]
diff --git a/libs/binder/trusty/ndk/include/sys/cdefs.h b/libs/binder/trusty/ndk/include/sys/cdefs.h
index 6a48d2b..eabfe60 100644
--- a/libs/binder/trusty/ndk/include/sys/cdefs.h
+++ b/libs/binder/trusty/ndk/include/sys/cdefs.h
@@ -22,3 +22,4 @@
 #define __END_DECLS __END_CDECLS
 
 #define __INTRODUCED_IN(x) /* nothing on Trusty */
+#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/ndk/rules.mk b/libs/binder/trusty/ndk/rules.mk
index 03fd006..7a275c2 100644
--- a/libs/binder/trusty/ndk/rules.mk
+++ b/libs/binder/trusty/ndk/rules.mk
@@ -23,6 +23,7 @@
 	$(LIBBINDER_NDK_DIR)/ibinder.cpp \
 	$(LIBBINDER_NDK_DIR)/libbinder.cpp \
 	$(LIBBINDER_NDK_DIR)/parcel.cpp \
+	$(LIBBINDER_NDK_DIR)/stability.cpp \
 	$(LIBBINDER_NDK_DIR)/status.cpp \
 
 MODULE_EXPORT_INCLUDES += \
diff --git a/libs/binder/trusty/rust/binder_rpc_test/aidl/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/aidl/rules.mk
new file mode 100644
index 0000000..1b0dca0
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/aidl/rules.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2023 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LIBBINDER_TESTS_DIR := $(LOCAL_DIR)/../../../../tests
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_AIDL_LANGUAGE := rust
+
+MODULE_CRATE_NAME := binder_rpc_test_aidl
+
+MODULE_AIDLS := \
+	$(LIBBINDER_TESTS_DIR)/BinderRpcTestClientInfo.aidl \
+	$(LIBBINDER_TESTS_DIR)/BinderRpcTestServerConfig.aidl \
+	$(LIBBINDER_TESTS_DIR)/BinderRpcTestServerInfo.aidl \
+	$(LIBBINDER_TESTS_DIR)/IBinderRpcCallback.aidl \
+	$(LIBBINDER_TESTS_DIR)/IBinderRpcSession.aidl \
+	$(LIBBINDER_TESTS_DIR)/IBinderRpcTest.aidl \
+	$(LIBBINDER_TESTS_DIR)/ParcelableCertificateData.aidl \
+
+include make/aidl.mk
diff --git a/libs/binder/trusty/rust/binder_rpc_test/main.rs b/libs/binder/trusty/rust/binder_rpc_test/main.rs
new file mode 100644
index 0000000..a71ce2c
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/main.rs
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+#![cfg(test)]
+
+use binder::{IBinder, Strong};
+use binder_rpc_test_aidl::aidl::IBinderRpcTest::IBinderRpcTest;
+use rpcbinder::RpcSession;
+use trusty_std::ffi::{CString, FallibleCString};
+
+test::init!();
+
+const SERVICE_PORT: &str = "com.android.trusty.binderRpcTestService.V1";
+
+fn get_service() -> Strong<dyn IBinderRpcTest> {
+    let port = CString::try_new(SERVICE_PORT).expect("Failed to allocate port name");
+    RpcSession::new().setup_trusty_client(port.as_c_str()).expect("Failed to create session")
+}
+
+#[test]
+fn ping() {
+    let srv = get_service();
+    assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/manifest.json b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
new file mode 100644
index 0000000..c2ecaa4
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
@@ -0,0 +1,9 @@
+{
+    "uuid": "91eed949-8a9e-4569-9c83-5935fb624025",
+    "app_name": "rust_binder_rpc_test",
+    "min_heap": 16384,
+    "min_stack": 16384,
+    "mgmt_flags": {
+        "non_critical_app": true
+    }
+}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
new file mode 100644
index 0000000..192a159
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2023 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LIBBINDER_DIR := $(LOCAL_DIR)/../../..
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LOCAL_DIR)/main.rs
+
+MODULE_CRATE_NAME := binder_rpc_test
+
+MODULE_LIBRARY_DEPS += \
+	$(LIBBINDER_DIR)/trusty/rust \
+	$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
+	$(LOCAL_DIR)/aidl \
+	trusty/user/base/lib/trusty-std \
+
+MODULE_RUST_TESTS := true
+
+MANIFEST := $(LOCAL_DIR)/manifest.json
+
+include make/library.mk
diff --git a/libs/binder/trusty/usertests-inc.mk b/libs/binder/trusty/usertests-inc.mk
index 1300121..241e668 100644
--- a/libs/binder/trusty/usertests-inc.mk
+++ b/libs/binder/trusty/usertests-inc.mk
@@ -17,3 +17,6 @@
 	frameworks/native/libs/binder/trusty/binderRpcTest \
 	frameworks/native/libs/binder/trusty/binderRpcTest/service \
 
+TRUSTY_RUST_USER_TESTS += \
+	frameworks/native/libs/binder/trusty/rust/binder_rpc_test \
+
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
index a8f2cbf..19f3aad 100644
--- a/libs/binderdebug/BinderDebug.cpp
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -199,4 +199,31 @@
     return ret;
 }
 
+status_t getBinderTransactions(pid_t pid, std::string& transactionsOutput) {
+    std::ifstream ifs("/dev/binderfs/binder_logs/transactions");
+    if (!ifs.is_open()) {
+        ifs.open("/d/binder/transactions");
+        if (!ifs.is_open()) {
+            LOG(ERROR) << "Could not open /dev/binderfs/binder_logs/transactions. "
+                       << "Likely a permissions issue. errno: " << errno;
+            return -errno;
+        }
+    }
+
+    std::string line;
+    while (getline(ifs, line)) {
+        // The section for this pid ends with another "proc <pid>" for another
+        // process. There is only one entry per pid so we can stop looking after
+        // we've grabbed the whole section
+        if (base::StartsWith(line, "proc " + std::to_string(pid))) {
+            do {
+                transactionsOutput += line + '\n';
+            } while (getline(ifs, line) && !base::StartsWith(line, "proc "));
+            return OK;
+        }
+    }
+
+    return NAME_NOT_FOUND;
+}
+
 } // namespace  android
diff --git a/libs/binderdebug/include/binderdebug/BinderDebug.h b/libs/binderdebug/include/binderdebug/BinderDebug.h
index 6ce8edf..018393c 100644
--- a/libs/binderdebug/include/binderdebug/BinderDebug.h
+++ b/libs/binderdebug/include/binderdebug/BinderDebug.h
@@ -44,4 +44,12 @@
 status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
                              int32_t handle, std::vector<pid_t>* pids);
 
+/**
+ * Get the transactions for a given process from /dev/binderfs/binder_logs/transactions
+ * Return: OK if the file was found and the pid was found in the file.
+ *         -errno if there was an issue opening the file
+ *         NAME_NOT_FOUND if the pid wasn't found in the file
+ */
+status_t getBinderTransactions(pid_t pid, std::string& transactionOutput);
+
 } // namespace  android
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index b5c4010..e888b0a 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -22,6 +22,7 @@
 #include <binderthreadstateutilstest/1.0/IHidlStuff.h>
 #include <gtest/gtest.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
 
 #include <thread>
@@ -37,6 +38,7 @@
 using android::sp;
 using android::String16;
 using android::binder::Status;
+using android::hardware::isHidlSupported;
 using android::hardware::Return;
 using binderthreadstateutilstest::V1_0::IHidlStuff;
 
@@ -67,6 +69,7 @@
 // complicated calls are possible, but this should do here.
 
 static void callHidl(size_t id, int32_t idx) {
+    CHECK_EQ(true, isHidlSupported()) << "We shouldn't be calling HIDL if it's not supported";
     auto stuff = IHidlStuff::getService(id2name(id));
     CHECK(stuff->call(idx).isOk());
 }
@@ -174,6 +177,7 @@
 }
 
 TEST(BindThreadState, RemoteHidlCall) {
+    if (!isHidlSupported()) GTEST_SKIP() << "No  HIDL support on device";
     auto stuff = IHidlStuff::getService(id2name(kP1Id));
     ASSERT_NE(nullptr, stuff);
     ASSERT_TRUE(stuff->call(0).isOk());
@@ -186,11 +190,14 @@
 }
 
 TEST(BindThreadState, RemoteNestedStartHidlCall) {
+    if (!isHidlSupported()) GTEST_SKIP() << "No  HIDL support on device";
     auto stuff = IHidlStuff::getService(id2name(kP1Id));
     ASSERT_NE(nullptr, stuff);
     ASSERT_TRUE(stuff->call(100).isOk());
 }
 TEST(BindThreadState, RemoteNestedStartAidlCall) {
+    // this test case is trying ot nest a HIDL call which requires HIDL support
+    if (!isHidlSupported()) GTEST_SKIP() << "No  HIDL support on device";
     sp<IAidlStuff> stuff;
     ASSERT_EQ(OK, android::getService<IAidlStuff>(String16(id2name(kP1Id).c_str()), &stuff));
     ASSERT_NE(nullptr, stuff);
@@ -205,11 +212,15 @@
              defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
     android::ProcessState::self()->startThreadPool();
 
-    // HIDL
-    android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
-    sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
-    CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str()));
-    android::hardware::joinRpcThreadpool();
+    if (isHidlSupported()) {
+        // HIDL
+        android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
+        sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
+        CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str()));
+        android::hardware::joinRpcThreadpool();
+    } else {
+        android::IPCThreadState::self()->joinThreadPool(true);
+    }
 
     return EXIT_FAILURE;
 }
@@ -227,9 +238,15 @@
     }
 
     android::waitForService<IAidlStuff>(String16(id2name(kP1Id).c_str()));
-    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP1Id).c_str());
+    if (isHidlSupported()) {
+        android::hardware::details::waitForHwService(IHidlStuff::descriptor,
+                                                     id2name(kP1Id).c_str());
+    }
     android::waitForService<IAidlStuff>(String16(id2name(kP2Id).c_str()));
-    android::hardware::details::waitForHwService(IHidlStuff::descriptor, id2name(kP2Id).c_str());
+    if (isHidlSupported()) {
+        android::hardware::details::waitForHwService(IHidlStuff::descriptor,
+                                                     id2name(kP2Id).c_str());
+    }
 
     return RUN_ALL_TESTS();
 }
diff --git a/libs/debugstore/OWNERS b/libs/debugstore/OWNERS
new file mode 100644
index 0000000..428a1a2
--- /dev/null
+++ b/libs/debugstore/OWNERS
@@ -0,0 +1,3 @@
+benmiles@google.com
+gaillard@google.com
+mohamadmahmoud@google.com
diff --git a/libs/debugstore/rust/Android.bp b/libs/debugstore/rust/Android.bp
new file mode 100644
index 0000000..55ba3c3
--- /dev/null
+++ b/libs/debugstore/rust/Android.bp
@@ -0,0 +1,71 @@
+// Copyright (C) 2024 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.
+
+package {
+    default_team: "trendy_team_android_telemetry_infra",
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+rust_defaults {
+    name: "libdebugstore_defaults",
+    srcs: ["src/lib.rs"],
+    rustlibs: [
+        "libcrossbeam_queue",
+        "libparking_lot",
+        "libonce_cell",
+        "libcxx",
+    ],
+    shared_libs: ["libutils"],
+    edition: "2021",
+}
+
+rust_ffi_static {
+    name: "libdebugstore_rust_ffi",
+    crate_name: "debugstore",
+    defaults: ["libdebugstore_defaults"],
+}
+
+cc_library {
+    name: "libdebugstore_cxx",
+    generated_headers: ["libdebugstore_cxx_bridge_header"],
+    generated_sources: ["libdebugstore_cxx_bridge_code"],
+    export_generated_headers: ["libdebugstore_cxx_bridge_header"],
+    shared_libs: ["libutils"],
+    whole_static_libs: ["libdebugstore_rust_ffi"],
+}
+
+rust_test {
+    name: "libdebugstore_tests",
+    defaults: ["libdebugstore_defaults"],
+    test_options: {
+        unit_test: true,
+    },
+    shared_libs: ["libdebugstore_cxx"],
+}
+
+genrule {
+    name: "libdebugstore_cxx_bridge_header",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
+    srcs: ["src/lib.rs"],
+    out: ["debugstore/debugstore_cxx_bridge.rs.h"],
+}
+
+genrule {
+    name: "libdebugstore_cxx_bridge_code",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) >> $(out)",
+    srcs: ["src/lib.rs"],
+    out: ["debugstore/debugstore_cxx_bridge.rs.cpp"],
+}
diff --git a/libs/debugstore/rust/Cargo.toml b/libs/debugstore/rust/Cargo.toml
new file mode 100644
index 0000000..23a8d24
--- /dev/null
+++ b/libs/debugstore/rust/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "debugstore"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+
+[dependencies]
\ No newline at end of file
diff --git a/libs/debugstore/rust/src/core.rs b/libs/debugstore/rust/src/core.rs
new file mode 100644
index 0000000..1dfa512
--- /dev/null
+++ b/libs/debugstore/rust/src/core.rs
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+use super::event::Event;
+use super::event_type::EventType;
+use super::storage::Storage;
+use crate::cxxffi::uptimeMillis;
+use once_cell::sync::Lazy;
+use std::fmt;
+use std::sync::atomic::{AtomicU64, Ordering};
+
+//  Lazily initialized static instance of DebugStore.
+static INSTANCE: Lazy<DebugStore> = Lazy::new(DebugStore::new);
+
+/// The `DebugStore` struct is responsible for managing debug events and data.
+pub struct DebugStore {
+    /// Atomic counter for generating unique event IDs.
+    id_generator: AtomicU64,
+    /// Non-blocking storage for debug events.
+    event_store: Storage<Event, { DebugStore::DEFAULT_EVENT_LIMIT }>,
+}
+
+impl DebugStore {
+    /// The default limit for the number of events that can be stored.
+    ///
+    /// This limit is used to initialize the storage for debug events.
+    const DEFAULT_EVENT_LIMIT: usize = 16;
+    /// A designated identifier used for events that cannot be closed.
+    ///
+    /// This ID is used for point/instantaneous events, or events do not have
+    ///  a distinct end.
+    const NON_CLOSABLE_ID: u64 = 0;
+    /// The version number for the encoding of debug store data.
+    ///
+    /// This constant is used as a part of the debug store's data format,
+    /// allowing for version tracking and compatibility checks.
+    const ENCODE_VERSION: u32 = 1;
+
+    /// Creates a new instance of `DebugStore` with specified event limit and maximum delay.
+    fn new() -> Self {
+        Self { id_generator: AtomicU64::new(1), event_store: Storage::new() }
+    }
+
+    /// Returns a shared instance of `DebugStore`.
+    ///
+    /// This method provides a singleton pattern access to `DebugStore`.
+    pub fn get_instance() -> &'static DebugStore {
+        &INSTANCE
+    }
+
+    /// Begins a new debug event with the given name and data.
+    ///
+    /// This method logs the start of a debug event, assigning it a unique ID and marking its start time.
+    /// - `name`: The name of the debug event.
+    /// - `data`: Associated data as key-value pairs.
+    /// - Returns: A unique ID for the debug event.
+    pub fn begin(&self, name: String, data: Vec<(String, String)>) -> u64 {
+        let id = self.generate_id();
+        self.event_store.insert(Event::new(
+            id,
+            Some(name),
+            uptimeMillis(),
+            EventType::DurationStart,
+            data,
+        ));
+        id
+    }
+
+    /// Records a debug event without a specific duration, with the given name and data.
+    ///
+    /// This method logs an instantaneous debug event, useful for events that don't have a duration but are significant.
+    /// - `name`: The name of the debug event.
+    /// - `data`: Associated data as key-value pairs.
+    pub fn record(&self, name: String, data: Vec<(String, String)>) {
+        self.event_store.insert(Event::new(
+            Self::NON_CLOSABLE_ID,
+            Some(name),
+            uptimeMillis(),
+            EventType::Point,
+            data,
+        ));
+    }
+
+    /// Ends a debug event that was previously started with the given ID.
+    ///
+    /// This method marks the end of a debug event, completing its lifecycle.
+    /// - `id`: The unique ID of the debug event to end.
+    /// - `data`: Additional data to log at the end of the event.
+    pub fn end(&self, id: u64, data: Vec<(String, String)>) {
+        if id != Self::NON_CLOSABLE_ID {
+            self.event_store.insert(Event::new(
+                id,
+                None,
+                uptimeMillis(),
+                EventType::DurationEnd,
+                data,
+            ));
+        }
+    }
+
+    fn generate_id(&self) -> u64 {
+        let mut id = self.id_generator.fetch_add(1, Ordering::Relaxed);
+        while id == Self::NON_CLOSABLE_ID {
+            id = self.id_generator.fetch_add(1, Ordering::Relaxed);
+        }
+        id
+    }
+}
+
+impl fmt::Display for DebugStore {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let uptime_now = uptimeMillis();
+        write!(f, "{},{},{}::", Self::ENCODE_VERSION, self.event_store.len(), uptime_now)?;
+
+        write!(
+            f,
+            "{}",
+            self.event_store.fold(String::new(), |mut acc, event| {
+                if !acc.is_empty() {
+                    acc.push_str("||");
+                }
+                acc.push_str(&event.to_string());
+                acc
+            })
+        )
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_begin_event() {
+        let debug_store = DebugStore::new();
+        let _event_id = debug_store.begin("test_event".to_string(), vec![]);
+        let output = debug_store.to_string();
+        assert!(
+            output.contains("test_event"),
+            "The output should contain the event name 'test_event'"
+        );
+    }
+
+    #[test]
+    fn test_unique_event_ids() {
+        let debug_store = DebugStore::new();
+        let event_id1 = debug_store.begin("event1".to_string(), vec![]);
+        let event_id2 = debug_store.begin("event2".to_string(), vec![]);
+        assert_ne!(event_id1, event_id2, "Event IDs should be unique");
+    }
+
+    #[test]
+    fn test_end_event() {
+        let debug_store = DebugStore::new();
+        let event_id = debug_store.begin("test_event".to_string(), vec![]);
+        debug_store.end(event_id, vec![]);
+        let output = debug_store.to_string();
+
+        let id_pattern = format!("ID:{},", event_id);
+        assert!(
+            output.contains("test_event"),
+            "The output should contain the event name 'test_event'"
+        );
+        assert_eq!(
+            output.matches(&id_pattern).count(),
+            2,
+            "The output should contain two events (start and end) associated with the given ID"
+        );
+    }
+
+    #[test]
+    fn test_event_data_handling() {
+        let debug_store = DebugStore::new();
+        debug_store
+            .record("data_event".to_string(), vec![("key".to_string(), "value".to_string())]);
+        let output = debug_store.to_string();
+        assert!(
+            output.contains("data_event"),
+            "The output should contain the event name 'data_event'"
+        );
+        assert!(
+            output.contains("key=value"),
+            "The output should contain the event data 'key=value'"
+        );
+    }
+}
diff --git a/libs/debugstore/rust/src/event.rs b/libs/debugstore/rust/src/event.rs
new file mode 100644
index 0000000..0c16665
--- /dev/null
+++ b/libs/debugstore/rust/src/event.rs
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+use super::event_type::EventType;
+use std::fmt;
+
+/// Represents a single debug event within the Debug Store system.
+///
+/// It contains all the necessary information for a debug event.
+#[derive(Clone)]
+pub struct Event {
+    /// The unique identifier for this event.
+    pub id: u64,
+    /// The optional name of the event.
+    pub name: Option<String>,
+    /// The system uptime when the event occurred.
+    pub timestamp: i64,
+    /// The type of the event.
+    pub event_type: EventType,
+    /// Additional data associated with the event, stored in the given order as key-value pairs.
+    data: Vec<(String, String)>,
+}
+
+impl Event {
+    /// Constructs a new `Event`.
+    ///
+    /// - `id`: The unique identifier for the event.
+    /// - `name`: An optional name for the event.
+    /// - `timestamp`: The system uptime when the event occurred.
+    /// - `event_type`: The type of the event.
+    /// - `data`: Additional data for the event, represented as ordered key-value pairs.
+    pub fn new(
+        id: u64,
+        name: Option<String>,
+        timestamp: i64,
+        event_type: EventType,
+        data: Vec<(String, String)>,
+    ) -> Self {
+        Self { id, name, timestamp, event_type, data }
+    }
+}
+
+impl fmt::Display for Event {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "ID:{},C:{},T:{}", self.id, self.event_type, self.timestamp)?;
+
+        if let Some(ref name) = self.name {
+            write!(f, ",N:{}", name)?;
+        }
+
+        if !self.data.is_empty() {
+            let data_str =
+                self.data.iter().map(|(k, v)| format!("{}={}", k, v)).collect::<Vec<_>>().join(";");
+            write!(f, ",D:{}", data_str)?;
+        }
+
+        Ok(())
+    }
+}
diff --git a/libs/debugstore/rust/src/event_type.rs b/libs/debugstore/rust/src/event_type.rs
new file mode 100644
index 0000000..6f4bafb
--- /dev/null
+++ b/libs/debugstore/rust/src/event_type.rs
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+use std::fmt;
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum EventType {
+    /// Marks the an unknown or invalid event, for convenient mapping to a protobuf enum.
+    Invalid,
+    /// Marks the beginning of a duration-based event, indicating the start of a timed operation.
+    DurationStart,
+    /// Marks the end of a duration-based event, indicating the end of a timed operation.
+    DurationEnd,
+    /// Represents a single, instantaneous event with no duration.
+    Point,
+}
+
+impl fmt::Display for EventType {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                EventType::Invalid => "I",
+                EventType::DurationStart => "S",
+                EventType::DurationEnd => "E",
+                EventType::Point => "P",
+            }
+        )
+    }
+}
diff --git a/libs/debugstore/rust/src/lib.rs b/libs/debugstore/rust/src/lib.rs
new file mode 100644
index 0000000..f2195c0
--- /dev/null
+++ b/libs/debugstore/rust/src/lib.rs
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! # Debug Store Crate
+/// The Debug Store Crate provides functionalities for storing debug events.
+/// It allows logging and retrieval of debug events, and associated data.
+mod core;
+mod event;
+mod event_type;
+mod storage;
+
+pub use core::*;
+pub use event::*;
+
+use cxx::{CxxString, CxxVector};
+
+#[cxx::bridge(namespace = "android::debugstore")]
+#[allow(unsafe_op_in_unsafe_fn)]
+mod cxxffi {
+    extern "Rust" {
+        fn debug_store_to_string() -> String;
+        fn debug_store_record(name: &CxxString, data: &CxxVector<CxxString>);
+        fn debug_store_begin(name: &CxxString, data: &CxxVector<CxxString>) -> u64;
+        fn debug_store_end(id: u64, data: &CxxVector<CxxString>);
+    }
+
+    #[namespace = "android"]
+    unsafe extern "C++" {
+        include!("utils/SystemClock.h");
+        fn uptimeMillis() -> i64;
+    }
+}
+
+fn debug_store_to_string() -> String {
+    DebugStore::get_instance().to_string()
+}
+
+fn debug_store_record(name: &CxxString, data: &CxxVector<CxxString>) {
+    DebugStore::get_instance().record(name.to_string_lossy().into_owned(), cxx_vec_to_pairs(data));
+}
+
+fn debug_store_begin(name: &CxxString, data: &CxxVector<CxxString>) -> u64 {
+    DebugStore::get_instance().begin(name.to_string_lossy().into_owned(), cxx_vec_to_pairs(data))
+}
+
+fn debug_store_end(id: u64, data: &CxxVector<CxxString>) {
+    DebugStore::get_instance().end(id, cxx_vec_to_pairs(data));
+}
+
+fn cxx_vec_to_pairs(vec: &CxxVector<CxxString>) -> Vec<(String, String)> {
+    vec.iter()
+        .map(|s| s.to_string_lossy().into_owned())
+        .collect::<Vec<_>>()
+        .chunks(2)
+        .filter_map(|chunk| match chunk {
+            [k, v] => Some((k.clone(), v.clone())),
+            _ => None,
+        })
+        .collect()
+}
diff --git a/libs/debugstore/rust/src/storage.rs b/libs/debugstore/rust/src/storage.rs
new file mode 100644
index 0000000..2ad7f4e
--- /dev/null
+++ b/libs/debugstore/rust/src/storage.rs
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+use crossbeam_queue::ArrayQueue;
+
+/// A thread-safe storage that allows non-blocking attempts to store and visit elements.
+pub struct Storage<T, const N: usize> {
+    insertion_buffer: ArrayQueue<T>,
+}
+
+impl<T, const N: usize> Storage<T, N> {
+    /// Creates a new Storage with the specified size.
+    pub fn new() -> Self {
+        Self { insertion_buffer: ArrayQueue::new(N) }
+    }
+
+    /// Inserts a value into the storage, returning an error if the lock cannot be acquired.
+    pub fn insert(&self, value: T) {
+        self.insertion_buffer.force_push(value);
+    }
+
+    /// Folds over the elements in the storage using the provided function.
+    pub fn fold<U, F>(&self, init: U, mut func: F) -> U
+    where
+        F: FnMut(U, &T) -> U,
+    {
+        let mut acc = init;
+        while let Some(value) = self.insertion_buffer.pop() {
+            acc = func(acc, &value);
+        }
+        acc
+    }
+
+    /// Returns the number of elements that have been inserted into the storage.
+    pub fn len(&self) -> usize {
+        self.insertion_buffer.len()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_insert_and_retrieve() {
+        let storage = Storage::<i32, 10>::new();
+        storage.insert(7);
+
+        let sum = storage.fold(0, |acc, &x| acc + x);
+        assert_eq!(sum, 7, "The sum of the elements should be equal to the inserted value.");
+    }
+
+    #[test]
+    fn test_fold_functionality() {
+        let storage = Storage::<i32, 5>::new();
+        storage.insert(1);
+        storage.insert(2);
+        storage.insert(3);
+
+        let sum = storage.fold(0, |acc, &x| acc + x);
+        assert_eq!(
+            sum, 6,
+            "The sum of the elements should be equal to the sum of inserted values."
+        );
+    }
+
+    #[test]
+    fn test_insert_and_retrieve_multiple_values() {
+        let storage = Storage::<i32, 10>::new();
+        storage.insert(1);
+        storage.insert(2);
+        storage.insert(5);
+
+        let first_sum = storage.fold(0, |acc, &x| acc + x);
+        assert_eq!(first_sum, 8, "The sum of the elements should be equal to the inserted values.");
+
+        storage.insert(30);
+        storage.insert(22);
+
+        let second_sum = storage.fold(0, |acc, &x| acc + x);
+        assert_eq!(
+            second_sum, 52,
+            "The sum of the elements should be equal to the inserted values."
+        );
+    }
+
+    #[test]
+    fn test_storage_limit() {
+        let storage = Storage::<i32, 1>::new();
+        storage.insert(1);
+        // This value should overwrite the previously inserted value (1).
+        storage.insert(4);
+        let sum = storage.fold(0, |acc, &x| acc + x);
+        assert_eq!(sum, 4, "The sum of the elements should be equal to the inserted values.");
+    }
+
+    #[test]
+    fn test_concurrent_insertions() {
+        use std::sync::Arc;
+        use std::thread;
+
+        let storage = Arc::new(Storage::<i32, 100>::new());
+        let threads: Vec<_> = (0..10)
+            .map(|_| {
+                let storage_clone = Arc::clone(&storage);
+                thread::spawn(move || {
+                    for i in 0..10 {
+                        storage_clone.insert(i);
+                    }
+                })
+            })
+            .collect();
+
+        for thread in threads {
+            thread.join().expect("Thread should finish without panicking");
+        }
+
+        let count = storage.fold(0, |acc, _| acc + 1);
+        assert_eq!(count, 100, "Storage should be filled to its limit with concurrent insertions.");
+    }
+}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8b6f202..079ccda 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2445,7 +2445,6 @@
                                                      const sp<IBinder>& parentHandle,
                                                      LayerMetadata metadata,
                                                      uint32_t* outTransformHint) {
-    sp<SurfaceControl> sur;
     status_t err = mStatus;
 
     if (mStatus == NO_ERROR) {
diff --git a/libs/nativewindow/rust/Android.bp b/libs/nativewindow/rust/Android.bp
index 90d0a8e..798d804 100644
--- a/libs/nativewindow/rust/Android.bp
+++ b/libs/nativewindow/rust/Android.bp
@@ -53,6 +53,10 @@
     },
     min_sdk_version: "VanillaIceCream",
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
 
 rust_library {
@@ -77,6 +81,10 @@
     },
     min_sdk_version: "VanillaIceCream",
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
 
 rust_test {
@@ -115,6 +123,10 @@
     },
     min_sdk_version: "VanillaIceCream",
     vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
 
 rust_test {
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index 22ad834..dc3f51f 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -16,7 +16,8 @@
 
 extern crate nativewindow_bindgen as ffi;
 
-pub mod surface;
+mod surface;
+pub use surface::Surface;
 
 pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
 
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index 90c2330..7347ac7 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1,3 +1 @@
-arthuri@google.com
 bduddie@google.com
-stange@google.com
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index 25850f7..303043a 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -22,6 +22,7 @@
 #include <aidlcommonsupport/NativeHandle.h>
 #include <android/binder_manager.h>
 #include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
+#include <android/llndk-versioning.h>
 #include <binder/IPCThreadState.h>
 #include <dlfcn.h>
 #include <ui/FatVector.h>
@@ -90,8 +91,7 @@
 
         void* so = nullptr;
         // TODO(b/322384429) switch this to __ANDROID_API_V__ when V is finalized
-        // TODO(b/302113279) use __ANDROID_VENDOR_API__ for vendor variant
-        if (__builtin_available(android __ANDROID_API_FUTURE__, *)) {
+        if API_LEVEL_AT_LEAST(__ANDROID_API_FUTURE__, 202404) {
             so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
                                                             RTLD_LOCAL | RTLD_NOW);
         } else {
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e487cbc..af0bcff 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -67,7 +67,6 @@
 static const char* RO_DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
 static const char* RO_BOARD_PLATFORM_PROPERTY = "ro.board.platform";
 static const char* ANGLE_SUFFIX_VALUE = "angle";
-static const char* VENDOR_ANGLE_BUILD = "ro.gfx.angle.supported";
 
 static const char* HAL_SUBNAME_KEY_PROPERTIES[3] = {
         PERSIST_DRIVER_SUFFIX_PROPERTY,
@@ -494,14 +493,9 @@
 
     void* dso = nullptr;
 
-    const bool AngleInVendor = property_get_bool(VENDOR_ANGLE_BUILD, false);
     const bool isSuffixAngle = suffix != nullptr && strcmp(suffix, ANGLE_SUFFIX_VALUE) == 0;
-    // Only use sphal namespace when system ANGLE binaries are not the default drivers.
-    const bool useSphalNamespace =  !isSuffixAngle || AngleInVendor;
-
     const std::string absolutePath =
-            findLibrary(libraryName, useSphalNamespace ? VENDOR_LIB_EGL_DIR : SYSTEM_LIB_PATH,
-                        exact);
+            findLibrary(libraryName, isSuffixAngle ? SYSTEM_LIB_PATH : VENDOR_LIB_EGL_DIR, exact);
     if (absolutePath.empty()) {
         // this happens often, we don't want to log an error
         return nullptr;
@@ -509,8 +503,9 @@
     const char* const driverAbsolutePath = absolutePath.c_str();
 
     // Currently the default driver is unlikely to be ANGLE on most devices,
-    // hence put this first.
-    if (useSphalNamespace) {
+    // hence put this first. Only use sphal namespace when system ANGLE binaries
+    // are not the default drivers.
+    if (!isSuffixAngle) {
         // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
         // the original routine when the namespace does not exist.
         // See /system/linkerconfig/contents/namespace for the configuration of the
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9a3fe43..67e48a2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4680,7 +4680,7 @@
             const bool isPointerEvent =
                     isFromSource(event->getSource(), AINPUT_SOURCE_CLASS_POINTER);
             // If a pointer event has no displayId specified, inject it to the default display.
-            const uint32_t displayId = isPointerEvent && (event->getDisplayId() == ADISPLAY_ID_NONE)
+            const int32_t displayId = isPointerEvent && (event->getDisplayId() == ADISPLAY_ID_NONE)
                     ? ADISPLAY_ID_DEFAULT
                     : event->getDisplayId();
             int32_t flags = motionEvent.getFlags();
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index 178c531..ca8cdc3 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -18,9 +18,6 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 
-// This is needed for stdint.h to define INT64_MAX in C++
-#define __STDC_LIMIT_MACROS
-
 #include <inttypes.h>
 
 #include <android-base/stringprintf.h>
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index 0aee7d4..ffc1dd7 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -2,7 +2,6 @@
 
 adyabr@google.com
 alecmouri@google.com
-chaviw@google.com
 domlaskowski@google.com
 jreck@google.com
 lpy@google.com
@@ -10,5 +9,6 @@
 racarr@google.com
 ramindani@google.com
 rnlee@google.com
+sallyqi@google.com
 scroggo@google.com
 vishnun@google.com
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c56dc83..f7cc13e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -72,6 +72,7 @@
 #include <gui/TraceUtils.h>
 #include <hidl/ServiceManagement.h>
 #include <layerproto/LayerProtoParser.h>
+#include <linux/sched/types.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
@@ -7565,20 +7566,6 @@
         return NO_ERROR;
     }
 
-    // Currently, there is no wrapper in bionic: b/183240349.
-    struct sched_attr {
-        uint32_t size;
-        uint32_t sched_policy;
-        uint64_t sched_flags;
-        int32_t sched_nice;
-        uint32_t sched_priority;
-        uint64_t sched_runtime;
-        uint64_t sched_deadline;
-        uint64_t sched_period;
-        uint32_t sched_util_min;
-        uint32_t sched_util_max;
-    };
-
     sched_attr attr = {};
     attr.size = sizeof(attr);
 
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index ddbf3e4..cb96e05 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -24,6 +24,7 @@
 
 #include <mutex>
 #include <optional>
+#include <set>
 #include <thread>
 
 #include "FrontEnd/DisplayInfo.h"