Merge "Increase frame history size when SF buffer queue size changes"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 5267b02..dff4c44 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -181,6 +181,8 @@
     chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable
     chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable
     chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/printk/console/enable
+    chmod 0666 /sys/kernel/tracing/events/printk/console/enable
 
     # disk
     chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
@@ -295,8 +297,18 @@
     write /sys/kernel/debug/tracing/synthetic_events "rss_stat_throttled unsigned int mm_id; unsigned int curr; int member; long size"
 
     # allow creating event triggers
-    chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
     chmod 0666 /sys/kernel/tracing/events/kmem/rss_stat/trigger
+    chmod 0666 /sys/kernel/debug/tracing/events/kmem/rss_stat/trigger
+
+    # allow enabling rss_stat_throttled
+    chmod 0666 /sys/kernel/tracing/events/synthetic/rss_stat_throttled/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/synthetic/rss_stat_throttled/enable
+
+on late-init && property:ro.boot.fastboot.boottrace=enabled
+    setprop debug.atrace.tags.enableflags 802922
+    setprop persist.traced.enable 0
+    write /sys/kernel/debug/tracing/tracing_on 1
+    write /sys/kernel/tracing/tracing_on 1
 
 # Only create the tracing instance if persist.mm_events.enabled
 # Attempting to remove the tracing instance after it has been created
@@ -386,6 +398,103 @@
     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
 
+# Handle hyp tracing instance
+on late-init && property:ro.boot.hypervisor.vm.supported=1
+
+# Hypervisor tracing instance doesn't support changing trace_clock
+    chmod 0440 /sys/kernel/debug/tracing/hyp/trace_clock
+    chmod 0440 /sys/kernel/tracing/hyp/trace_clock
+
+    chmod 0660 /sys/kernel/debug/tracing/hyp/buffer_size_kb
+    chmod 0660 /sys/kernel/tracing/hyp/buffer_size_kb
+
+    chmod 0660 /sys/kernel/debug/tracing/hyp/tracing_on
+    chmod 0660 /sys/kernel/tracing/hyp/tracing_on
+
+# Tracing disabled by default
+    write /sys/kernel/debug/tracing/hyp/tracing_on 0
+    write /sys/kernel/tracing/hyp/tracing_on 0
+
+# Read and truncate the hyp trace.
+    chmod 0660 /sys/kernel/debug/tracing/hyp/trace
+    chmod 0660 /sys/kernel/tracing/hyp/trace
+
+# Read and truncate the per-CPU kernel trace.
+# Cannot use wildcards in .rc files. Update this if there is a phone with
+# TODO(b/249050813, ioffe): introduce per-cpu wildcard
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu0/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu0/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu1/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu1/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu2/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu2/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu3/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu3/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu4/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu4/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu5/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu5/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu6/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu6/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu7/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu7/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu8/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu8/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu9/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu9/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu10/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu10/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu11/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu11/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu12/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu12/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu13/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu13/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu14/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu14/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu15/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu15/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu16/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu16/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu17/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu17/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu18/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu18/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu19/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu19/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu20/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu20/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu21/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu21/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu22/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu22/trace
+    chmod 0660 /sys/kernel/debug/tracing/hyp/per_cpu/cpu23/trace
+    chmod 0660 /sys/kernel/tracing/hyp/per_cpu/cpu23/trace
+
+    chmod 0440 /sys/kernel/debug/tracing/hyp/events/header_page
+    chmod 0440 /sys/kernel/tracing/hyp/events/header_page
+
+# Hyp events start here
+
+# hyp_enter event
+    chmod 0660 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_enter/enable
+    chmod 0660 /sys/kernel/tracing/hyp/events/hyp/hyp_enter/enable
+# TODO(b/249050813): should this be handled in kernel?
+    chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_enter/format
+    chmod 0440 /sys/kernel/tracing/hyp/events/hyp/hyp_enter/format
+    chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_enter/id
+    chmod 0440 /sys/kernel/tracing/hyp/events/hyp/hyp_enter/id
+
+# hyp_exit event
+    chmod 0660 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_exit/enable
+    chmod 0660 /sys/kernel/tracing/hyp/events/hyp/hyp_exit/enable
+# TODO(b/249050813): should this be handled in kernel?
+    chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_exit/format
+    chmod 0440 /sys/kernel/tracing/hyp/events/hyp/hyp_exit/format
+    chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_exit/id
+    chmod 0440 /sys/kernel/tracing/hyp/events/hyp/hyp_exit/id
+
+
 on property:persist.debug.atrace.boottrace=1
     start boottrace
 
@@ -393,3 +502,10 @@
 service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
     disabled
     oneshot
+
+on property:sys.boot_completed=1 && property:ro.boot.fastboot.boottrace=enabled
+    setprop debug.atrace.tags.enableflags 0
+    setprop persist.traced.enable 1
+    write /sys/kernel/debug/tracing/tracing_on 0
+    write /sys/kernel/tracing/tracing_on 0
+
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index 5f56531..ab81ecf 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -3,3 +3,4 @@
 gavincorkery@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 47a513b..8c77255 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1252,8 +1252,9 @@
              dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
              dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
         } else {
-            status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
-            if (status == OK) {
+             status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID,
+                                                       service, args);
+             if (status == OK) {
                 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
                 std::chrono::duration<double> elapsed_seconds;
                 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
@@ -1895,6 +1896,9 @@
     }
     ds.AddDir(PREREBOOT_DATA_DIR, false);
     add_mountinfo();
+    for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
+        ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
+    }
     DumpIpTablesAsRoot();
     DumpDynamicPartitionInfo();
     ds.AddDir(OTA_METADATA_DIR, true);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 34ea759..794750f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -442,6 +442,16 @@
 static unique_fd open_reference_profile(uid_t uid, const std::string& package_name,
         const std::string& location, bool read_write, bool is_secondary_dex) {
     std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex);
+    if (read_write && GetBoolProperty("dalvik.vm.useartservice", false)) {
+        // ART Service doesn't use flock and instead assumes profile files are
+        // immutable, so ensure we don't open a file for writing when it's
+        // active.
+        // TODO(b/251921228): Normally installd isn't called at all in that
+        // case, but OTA is still an exception that uses the legacy code.
+        LOG(ERROR) << "Opening ref profile " << profile
+                   << " for writing is unsafe when ART Service is enabled.";
+        return invalid_unique_fd();
+    }
     return open_profile(
         uid,
         profile,
@@ -450,14 +460,13 @@
 }
 
 static UniqueFile open_reference_profile_as_unique_file(uid_t uid, const std::string& package_name,
-        const std::string& location, bool read_write, bool is_secondary_dex) {
+                                                        const std::string& location,
+                                                        bool is_secondary_dex) {
     std::string profile_path = create_reference_profile_path(package_name, location,
                                                              is_secondary_dex);
-    unique_fd ufd = open_profile(
-        uid,
-        profile_path,
-        read_write ? (O_CREAT | O_RDWR) : O_RDONLY,
-        S_IRUSR | S_IWUSR | S_IRGRP);  // so that ART can also read it when apps run.
+    unique_fd ufd = open_profile(uid, profile_path, O_RDONLY,
+                                 S_IRUSR | S_IWUSR |
+                                         S_IRGRP); // so that ART can also read it when apps run.
 
     return UniqueFile(ufd.release(), profile_path, [](const std::string& path) {
         clear_profile(path);
@@ -1104,8 +1113,7 @@
             location = profile_name;
         }
     }
-    return open_reference_profile_as_unique_file(uid, pkgname, location, /*read_write*/false,
-                                                 is_secondary_dex);
+    return open_reference_profile_as_unique_file(uid, pkgname, location, is_secondary_dex);
 }
 
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper and the output fd to
@@ -1909,10 +1917,11 @@
     // Open the reference profile if needed.
     UniqueFile reference_profile = maybe_open_reference_profile(
             pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
-
-    if (reference_profile.fd() == -1) {
-        // We don't create an app image without reference profile since there is no speedup from
-        // loading it in that case and instead will be a small overhead.
+    struct stat sbuf;
+    if (reference_profile.fd() == -1 ||
+        (fstat(reference_profile.fd(), &sbuf) != -1 && sbuf.st_size == 0)) {
+        // We don't create an app image with empty or non existing reference profile since there
+        // is no speedup from loading it in that case and instead will be a small overhead.
         generate_app_image = false;
     }
 
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 6a3120c..bf2c0d1 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -308,7 +308,7 @@
         // This is different from the normal installd. We only do the base
         // directory, the rest will be created on demand when each app is compiled.
         if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
-            LOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
+            PLOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
             return false;
         }
 
@@ -460,7 +460,7 @@
         // this tool will wipe the OTA artifact cache and try again (for robustness after
         // a failed OTA with remaining cache artifacts).
         if (access(apk_path, F_OK) != 0) {
-            LOG(WARNING) << "Skipping A/B OTA preopt of non-existing package " << apk_path;
+            PLOG(WARNING) << "Skipping A/B OTA preopt of non-existing package " << apk_path;
             return true;
         }
 
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c62734a..1b7acab 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -45,6 +45,10 @@
 namespace android {
 namespace installd {
 
+// We don't know the filesystem types of the partitions in the update package,
+// so just try the possibilities one by one.
+static constexpr std::array kTryMountFsTypes = {"ext4", "erofs"};
+
 static void CloseDescriptor(int fd) {
     if (fd >= 0) {
         int result = close(fd);
@@ -82,6 +86,27 @@
     }
 }
 
+static bool TryMountWithFstypes(const char* block_device, const char* target) {
+    for (int i = 0; i < kTryMountFsTypes.size(); ++i) {
+        const char* fstype = kTryMountFsTypes[i];
+        int mount_result = mount(block_device, target, fstype, MS_RDONLY, /* data */ nullptr);
+        if (mount_result == 0) {
+            return true;
+        }
+        if (errno == EINVAL && i < kTryMountFsTypes.size() - 1) {
+            // Only try the next fstype if mounting failed due to the current one
+            // being invalid.
+            LOG(WARNING) << "Failed to mount " << block_device << " on " << target << " with "
+                         << fstype << " - trying " << kTryMountFsTypes[i + 1];
+        } else {
+            PLOG(ERROR) << "Failed to mount " << block_device << " on " << target << " with "
+                        << fstype;
+            return false;
+        }
+    }
+    __builtin_unreachable();
+}
+
 static void TryExtraMount(const char* name, const char* slot, const char* target) {
     std::string partition_name = StringPrintf("%s%s", name, slot);
 
@@ -91,12 +116,7 @@
         if (dm.GetState(partition_name) != dm::DmDeviceState::INVALID) {
             std::string path;
             if (dm.GetDmDevicePathByName(partition_name, &path)) {
-                int mount_result = mount(path.c_str(),
-                                         target,
-                                         "ext4",
-                                         MS_RDONLY,
-                                         /* data */ nullptr);
-                if (mount_result == 0) {
+                if (TryMountWithFstypes(path.c_str(), target)) {
                     return;
                 }
             }
@@ -105,12 +125,7 @@
 
     // Fall back and attempt a direct mount.
     std::string block_device = StringPrintf("/dev/block/by-name/%s", partition_name.c_str());
-    int mount_result = mount(block_device.c_str(),
-                             target,
-                             "ext4",
-                             MS_RDONLY,
-                             /* data */ nullptr);
-    UNUSED(mount_result);
+    (void)TryMountWithFstypes(block_device.c_str(), target);
 }
 
 // Entry for otapreopt_chroot. Expected parameters are:
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index f950276..db5c34e 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -60,6 +60,11 @@
 
 i=0
 while ((i<MAXIMUM_PACKAGES)) ; do
+  DONE=$(cmd otadexopt done)
+  if [ "$DONE" = "OTA complete." ] ; then
+    break
+  fi
+
   DEXOPT_PARAMS=$(cmd otadexopt next)
 
   /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX $DEXOPT_PARAMS >&- 2>&-
@@ -67,13 +72,8 @@
   PROGRESS=$(cmd otadexopt progress)
   print -u${STATUS_FD} "global_progress $PROGRESS"
 
-  DONE=$(cmd otadexopt done)
-  if [ "$DONE" = "OTA incomplete." ] ; then
-    sleep 1
-    i=$((i+1))
-    continue
-  fi
-  break
+  sleep 1
+  i=$((i+1))
 done
 
 DONE=$(cmd otadexopt done)
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 3b589dc..5c4e1a4 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -185,7 +185,7 @@
     std::optional<std::string> volume_uuid_;
     std::string package_name_;
     std::string apk_path_;
-    std::string empty_dm_file_;
+    std::string dm_file_;
     std::string app_apk_dir_;
     std::string app_private_dir_ce_;
     std::string app_private_dir_de_;
@@ -248,26 +248,6 @@
                                                  << " : " << error_msg;
         }
 
-        // Create an empty dm file.
-        empty_dm_file_ = apk_path_ + ".dm";
-        {
-            int fd = open(empty_dm_file_.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
-            if (fd < 0) {
-                return ::testing::AssertionFailure() << "Could not open " << empty_dm_file_;
-            }
-            FILE* file = fdopen(fd, "wb");
-            if (file == nullptr) {
-                return ::testing::AssertionFailure() << "Null file for " << empty_dm_file_
-                         << " fd=" << fd;
-            }
-            ZipWriter writer(file);
-            // Add vdex to zip.
-            writer.StartEntry("primary.prof", ZipWriter::kCompress);
-            writer.FinishEntry();
-            writer.Finish();
-            fclose(file);
-          }
-
         // Create the app user data.
         binder::Status status = service_->createAppData(
                 volume_uuid_,
@@ -316,6 +296,46 @@
                                                  << secondary_dex_de_ << " : " << error_msg;
         }
 
+        // Create a non-empty dm file.
+        dm_file_ = apk_path_ + ".dm";
+        {
+            android::base::unique_fd fd(open(dm_file_.c_str(),
+                                          O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
+            if (fd.get() < 0) {
+                return ::testing::AssertionFailure() << "Could not open " << dm_file_;
+            }
+            FILE* file = fdopen(fd.release(), "wb");
+            if (file == nullptr) {
+                return ::testing::AssertionFailure() << "Null file for " << dm_file_
+                                  << " fd=" << fd.get();
+            }
+
+            // Create a profile file.
+            std::string profile_file = app_private_dir_ce_ + "/primary.prof";
+            run_cmd("profman --generate-test-profile=" + profile_file);
+
+            // Add profile to zip.
+            ZipWriter writer(file);
+            writer.StartEntry("primary.prof", ZipWriter::kCompress);
+            android::base::unique_fd profile_fd(open(profile_file.c_str(), O_RDONLY));
+            if (profile_fd.get() < 0) {
+                return ::testing::AssertionFailure() << "Failed to open profile '"
+                                  << profile_file << "'";
+            }
+            std::string profile_content;
+            if (!android::base::ReadFdToString(profile_fd, &profile_content)) {
+                return ::testing::AssertionFailure() << "Failed to read profile "
+                                  << profile_file << "'";
+            }
+            writer.WriteBytes(profile_content.c_str(), profile_content.length());
+            writer.FinishEntry();
+            writer.Finish();
+            fclose(file);
+
+            // Delete the temp file.
+            unlink(profile_file.c_str());
+        }
+
         // Fix app data uid.
         status = service_->fixupAppData(volume_uuid_, kTestUserId);
         if (!status.isOk()) {
@@ -608,7 +628,7 @@
                 kTestAppGid,
                 DEX2OAT_FROM_SCRATCH,
                 /*binder_result=*/nullptr,
-                empty_dm_file_.c_str());
+                dm_file_.c_str());
 
 
         int64_t odex_size = GetSize(GetPrimaryDexArtifact(oat_dir, apk_path_,
@@ -657,13 +677,13 @@
                             DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC |
                                     DEXOPT_GENERATE_APP_IMAGE,
                             oat_dir, kTestAppGid, DEX2OAT_FROM_SCRATCH,
-                            /*binder_result=*/nullptr, empty_dm_file_.c_str());
+                            /*binder_result=*/nullptr, dm_file_.c_str());
         checkVisibility(in_dalvik_cache, ODEX_IS_PUBLIC);
 
         CompilePrimaryDexOk("speed-profile",
                             DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
                             oat_dir, kTestAppGid, DEX2OAT_FROM_SCRATCH,
-                            /*binder_result=*/nullptr, empty_dm_file_.c_str());
+                            /*binder_result=*/nullptr, dm_file_.c_str());
         checkVisibility(in_dalvik_cache, ODEX_IS_PRIVATE);
     }
 };
@@ -787,7 +807,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
@@ -799,7 +819,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
@@ -811,7 +831,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
 }
 
 TEST_F(DexoptTest, DexoptBlockPrimary) {
@@ -874,7 +894,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
@@ -893,7 +913,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
     run_cmd_and_process_output(
             "oatdump --header-only --oat-file=" + odex,
             [&](const std::string& line) {
@@ -926,7 +946,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
     // Enable the property and use dex2oat64.
     ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
     CompilePrimaryDexOk("speed-profile",
@@ -936,7 +956,7 @@
                         kTestAppGid,
                         DEX2OAT_FROM_SCRATCH,
                         /*binder_result=*/nullptr,
-                        empty_dm_file_.c_str());
+                        dm_file_.c_str());
 }
 
 class PrimaryDexReCompilationTest : public DexoptTest {
@@ -1143,7 +1163,7 @@
                 service_->prepareAppProfile(package_name, has_user_id ? kTestUserId : USER_NULL,
                                             kTestAppId, profile_name, apk_path_,
                                             has_dex_metadata ? std::make_optional<std::string>(
-                                                                       empty_dm_file_)
+                                                                       dm_file_)
                                                              : std::nullopt,
                                             &result));
         ASSERT_EQ(expected_result, result);
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index d5ca725..5e8ef5d 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -75,7 +75,7 @@
     ProcessState::initWithDriver("/dev/vndbinder");
 #endif
 #ifndef __ANDROID__
-    setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingThreads = 1}));
+    setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingConnections = 1}));
 #endif
     sp<IServiceManager> sm = defaultServiceManager();
     fflush(stdout);
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index eadf678..bec262e 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -223,8 +223,13 @@
 #endif  // !VENDORSERVICEMANAGER
 
 ServiceManager::Service::~Service() {
-    if (!hasClients) {
-        // only expected to happen on process death
+    if (hasClients) {
+        // only expected to happen on process death, we don't store the service
+        // name this late (it's in the map that holds this service), but if it
+        // is happening, we might want to change 'unlinkToDeath' to explicitly
+        // 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";
     }
 }
diff --git a/include/android/OWNERS b/include/android/OWNERS
new file mode 100644
index 0000000..38f9c55
--- /dev/null
+++ b/include/android/OWNERS
@@ -0,0 +1 @@
+per-file input.h, keycodes.h = file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/include/input/Input.h b/include/input/Input.h
index 7ea2970..1eda981 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -818,6 +818,8 @@
                                                const PointerCoords&);
     static PointerCoords calculateTransformedCoords(uint32_t source, const ui::Transform&,
                                                     const PointerCoords&);
+    // The rounding precision for transformed motion events.
+    static constexpr float ROUNDING_PRECISION = 0.001f;
 
 protected:
     int32_t mAction;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index aec3080..baeb565 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -74,9 +74,6 @@
     name: "libbinder_common_defaults",
     host_supported: true,
 
-    // for vndbinder and binderRpcTest
-    vendor_available: true,
-
     srcs: [
         "Binder.cpp",
         "BpBinder.cpp",
@@ -200,7 +197,6 @@
 
 cc_library_headers {
     name: "trusty_mock_headers",
-    vendor_available: true,
     host_supported: true,
 
     export_include_dirs: [
@@ -215,7 +211,6 @@
 
 cc_defaults {
     name: "trusty_mock_defaults",
-    vendor_available: true,
     host_supported: true,
 
     header_libs: [
@@ -309,6 +304,8 @@
 
     version_script: "libbinder.map",
 
+    // for vndbinder
+    vendor_available: true,
     vndk: {
         enabled: true,
     },
@@ -471,7 +468,6 @@
 cc_library_static {
     name: "libbinder_tls_static",
     defaults: ["libbinder_tls_defaults"],
-    vendor_available: true,
     visibility: [
         ":__subpackages__",
     ],
@@ -556,6 +552,7 @@
         "//packages/modules/Virtualization/javalib/jni",
         "//packages/modules/Virtualization/vm_payload",
         "//device/google/cuttlefish/shared/minidroid:__subpackages__",
+        "//system/software_defined_vehicle:__subpackages__",
     ],
 }
 
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index 2e70304..ef58ed3 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/scopeguard.h>
 #include <android-base/unique_fd.h>
 #include <binder/RecordedTransaction.h>
 #include <sys/mman.h>
@@ -126,8 +127,7 @@
     t.mData.mInterfaceName = std::string(String8(interfaceName).string());
     if (interfaceName.size() != t.mData.mInterfaceName.size()) {
         LOG(ERROR) << "Interface Name is not valid. Contains characters that aren't single byte "
-                      "utf-8: "
-                   << interfaceName;
+                      "utf-8.";
         return std::nullopt;
     }
 
@@ -176,13 +176,33 @@
     RecordedTransaction t;
     ChunkDescriptor chunk;
     const long pageSize = sysconf(_SC_PAGE_SIZE);
+    struct stat fileStat;
+    if (fstat(fd.get(), &fileStat) != 0) {
+        LOG(ERROR) << "Unable to get file information";
+        return std::nullopt;
+    }
+
+    off_t fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
+    if (fdCurrentPosition == -1) {
+        LOG(ERROR) << "Invalid offset in file descriptor.";
+        return std::nullopt;
+    }
     do {
+        if (fileStat.st_size < (fdCurrentPosition + (off_t)sizeof(ChunkDescriptor))) {
+            LOG(ERROR) << "Not enough file remains to contain expected chunk descriptor";
+            return std::nullopt;
+        }
         transaction_checksum_t checksum = 0;
         if (NO_ERROR != readChunkDescriptor(fd, &chunk, &checksum)) {
             LOG(ERROR) << "Failed to read chunk descriptor.";
             return std::nullopt;
         }
-        off_t fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
+
+        fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
+        if (fdCurrentPosition == -1) {
+            LOG(ERROR) << "Invalid offset in file descriptor.";
+            return std::nullopt;
+        }
         off_t mmapPageAlignedStart = (fdCurrentPosition / pageSize) * pageSize;
         off_t mmapPayloadStartOffset = fdCurrentPosition - mmapPageAlignedStart;
 
@@ -194,14 +214,24 @@
         size_t chunkPayloadSize =
                 chunk.dataSize + PADDING8(chunk.dataSize) + sizeof(transaction_checksum_t);
 
+        if (chunkPayloadSize > (size_t)(fileStat.st_size - fdCurrentPosition)) {
+            LOG(ERROR) << "Chunk payload exceeds remaining file size.";
+            return std::nullopt;
+        }
+
         if (PADDING8(chunkPayloadSize) != 0) {
             LOG(ERROR) << "Invalid chunk size, not aligned " << chunkPayloadSize;
             return std::nullopt;
         }
 
-        transaction_checksum_t* payloadMap = reinterpret_cast<transaction_checksum_t*>(
-                mmap(NULL, chunkPayloadSize + mmapPayloadStartOffset, PROT_READ, MAP_SHARED,
-                     fd.get(), mmapPageAlignedStart));
+        size_t memoryMappedSize = chunkPayloadSize + mmapPayloadStartOffset;
+        void* mappedMemory =
+                mmap(NULL, memoryMappedSize, PROT_READ, MAP_SHARED, fd.get(), mmapPageAlignedStart);
+        auto mmap_guard = android::base::make_scope_guard(
+                [mappedMemory, memoryMappedSize] { munmap(mappedMemory, memoryMappedSize); });
+
+        transaction_checksum_t* payloadMap =
+                reinterpret_cast<transaction_checksum_t*>(mappedMemory);
         payloadMap += mmapPayloadStartOffset /
                 sizeof(transaction_checksum_t); // Skip chunk descriptor and required mmap
                                                 // page-alignment
@@ -218,7 +248,12 @@
             LOG(ERROR) << "Checksum failed.";
             return std::nullopt;
         }
-        lseek(fd.get(), chunkPayloadSize, SEEK_CUR);
+
+        fdCurrentPosition = lseek(fd.get(), chunkPayloadSize, SEEK_CUR);
+        if (fdCurrentPosition == -1) {
+            LOG(ERROR) << "Invalid offset in file descriptor.";
+            return std::nullopt;
+        }
 
         switch (chunk.chunkType) {
             case HEADER_CHUNK: {
@@ -255,7 +290,7 @@
                 break;
             default:
                 LOG(INFO) << "Unrecognized chunk.";
-                continue;
+                break;
         }
     } while (chunk.chunkType != END_CHUNK);
 
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index ce6ef2b..fbad0f7 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -20,6 +20,7 @@
 
 #include <dlfcn.h>
 #include <inttypes.h>
+#include <netinet/tcp.h>
 #include <poll.h>
 #include <unistd.h>
 
@@ -90,16 +91,16 @@
     return mMaxIncomingThreads;
 }
 
-void RpcSession::setMaxOutgoingThreads(size_t threads) {
+void RpcSession::setMaxOutgoingConnections(size_t connections) {
     RpcMutexLockGuard _l(mMutex);
     LOG_ALWAYS_FATAL_IF(mStartedSetup,
                         "Must set max outgoing threads before setting up connections");
-    mMaxOutgoingThreads = threads;
+    mMaxOutgoingConnections = connections;
 }
 
 size_t RpcSession::getMaxOutgoingThreads() {
     RpcMutexLockGuard _l(mMutex);
-    return mMaxOutgoingThreads;
+    return mMaxOutgoingConnections;
 }
 
 bool RpcSession::setProtocolVersionInternal(uint32_t version, bool checkStarted) {
@@ -558,11 +559,11 @@
         return status;
     }
 
-    size_t outgoingThreads = std::min(numThreadsAvailable, mMaxOutgoingThreads);
-    ALOGI_IF(outgoingThreads != numThreadsAvailable,
+    size_t outgoingConnections = std::min(numThreadsAvailable, mMaxOutgoingConnections);
+    ALOGI_IF(outgoingConnections != numThreadsAvailable,
              "Server hints client to start %zu outgoing threads, but client will only start %zu "
              "because it is preconfigured to start at most %zu outgoing threads.",
-             numThreadsAvailable, outgoingThreads, mMaxOutgoingThreads);
+             numThreadsAvailable, outgoingConnections, mMaxOutgoingConnections);
 
     // TODO(b/189955605): we should add additional sessions dynamically
     // instead of all at once - the other side should be responsible for setting
@@ -571,10 +572,10 @@
     // any requests at all.
 
     // we've already setup one client
-    LOG_RPC_DETAIL("RpcSession::setupClient() instantiating %zu outgoing (server max: %zu) and %zu "
-                   "incoming threads",
-                   outgoingThreads, numThreadsAvailable, mMaxIncomingThreads);
-    for (size_t i = 0; i + 1 < outgoingThreads; i++) {
+    LOG_RPC_DETAIL("RpcSession::setupClient() instantiating %zu outgoing connections (server max: "
+                   "%zu) and %zu incoming threads",
+                   outgoingConnections, numThreadsAvailable, mMaxIncomingThreads);
+    for (size_t i = 0; i + 1 < outgoingConnections; i++) {
         if (status_t status = connectAndInit(mId, false /*incoming*/); status != OK) return status;
     }
 
@@ -608,6 +609,18 @@
             return -savedErrno;
         }
 
+        if (addr.addr()->sa_family == AF_INET || addr.addr()->sa_family == AF_INET6) {
+            int noDelay = 1;
+            int result =
+                    setsockopt(serverFd.get(), IPPROTO_TCP, TCP_NODELAY, &noDelay, sizeof(noDelay));
+            if (result < 0) {
+                int savedErrno = errno;
+                ALOGE("Could not set TCP_NODELAY on %s: %s", addr.toString().c_str(),
+                      strerror(savedErrno));
+                return -savedErrno;
+            }
+        }
+
         RpcTransportFd transportFd(std::move(serverFd));
 
         if (0 != TEMP_FAILURE_RETRY(connect(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
@@ -932,7 +945,8 @@
                   (session->server()
                            ? "This is a server session, so see RpcSession::setMaxIncomingThreads "
                              "for the corresponding client"
-                           : "This is a client session, so see RpcSession::setMaxOutgoingThreads "
+                           : "This is a client session, so see "
+                             "RpcSession::setMaxOutgoingConnections "
                              "for this client or RpcServer::setMaxThreads for the corresponding "
                              "server"));
             return WOULD_BLOCK;
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index b27f102..38bd081 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -557,13 +557,12 @@
             .parcelDataSize = static_cast<uint32_t>(data.dataSize()),
     };
 
-    constexpr size_t kWaitMaxUs = 1000000;
-    constexpr size_t kWaitLogUs = 10000;
-    size_t waitUs = 0;
-
     // Oneway calls have no sync point, so if many are sent before, whether this
     // is a twoway or oneway transaction, they may have filled up the socket.
     // So, make sure we drain them before polling
+    constexpr size_t kWaitMaxUs = 1000000;
+    constexpr size_t kWaitLogUs = 10000;
+    size_t waitUs = 0;
 
     iovec iovs[]{
             {&command, sizeof(RpcWireHeader)},
@@ -591,8 +590,9 @@
                 },
                 rpcFields->mFds.get());
         status != OK) {
-        // TODO(b/167966510): need to undo onBinderLeaving - we know the
-        // refcount isn't successfully transferred.
+        // rpcSend calls shutdownAndWait, so all refcounts should be reset. If we ever tolerate
+        // errors here, then we may need to undo the binder-sent counts for the transaction as
+        // well as for the binder objects in the Parcel
         return status;
     }
 
@@ -1036,8 +1036,8 @@
                 return DEAD_OBJECT;
             }
 
-            if (it->second.asyncTodo.size() == 0) return OK;
-            if (it->second.asyncTodo.top().asyncNumber == it->second.asyncNumber) {
+            if (it->second.asyncTodo.size() != 0 &&
+                it->second.asyncTodo.top().asyncNumber == it->second.asyncNumber) {
                 LOG_RPC_DETAIL("Found next async transaction %" PRIu64 " on %" PRIu64,
                                it->second.asyncNumber, addr);
 
diff --git a/libs/binder/ServiceManagerHost.cpp b/libs/binder/ServiceManagerHost.cpp
index 194254a..2b67f03 100644
--- a/libs/binder/ServiceManagerHost.cpp
+++ b/libs/binder/ServiceManagerHost.cpp
@@ -159,8 +159,8 @@
     LOG_ALWAYS_FATAL_IF(!forwardResult->hostPort().has_value());
 
     auto rpcSession = RpcSession::make();
-    if (options.maxOutgoingThreads.has_value()) {
-        rpcSession->setMaxOutgoingThreads(*options.maxOutgoingThreads);
+    if (options.maxOutgoingConnections.has_value()) {
+        rpcSession->setMaxOutgoingConnections(*options.maxOutgoingConnections);
     }
 
     if (status_t status = rpcSession->setupInetClient("127.0.0.1", *forwardResult->hostPort());
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 1488400..07b38d7 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -119,5 +119,10 @@
     {
       "name": "memunreachable_binder_test"
     }
+  ],
+  "imports": [
+    {
+      "path": "packages/modules/Virtualization"
+    }
   ]
 }
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index c78f870..55167a7 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -224,12 +224,12 @@
 //    }
 // Resources are cleaned up when the object is destroyed.
 //
-// For each returned binder object, at most |maxOutgoingThreads| outgoing threads are instantiated.
-// Hence, only |maxOutgoingThreads| calls can be made simultaneously. Additional calls are blocked
-// if there are |maxOutgoingThreads| ongoing calls. See RpcSession::setMaxOutgoingThreads.
-// If |maxOutgoingThreads| is not set, default is |RpcSession::kDefaultMaxOutgoingThreads|.
+// For each returned binder object, at most |maxOutgoingConnections| outgoing connections are
+// instantiated, depending on how many the service on the device is configured with.
+// Hence, only |maxOutgoingConnections| calls can be made simultaneously.
+// See also RpcSession::setMaxOutgoingConnections.
 struct RpcDelegateServiceManagerOptions {
-    std::optional<size_t> maxOutgoingThreads;
+    std::optional<size_t> maxOutgoingConnections;
 };
 sp<IServiceManager> createRpcDelegateServiceManager(
         const RpcDelegateServiceManagerOptions& options);
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 25193a3..1001b64 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -119,7 +119,10 @@
     [[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd);
 
     /**
-     * This must be called before adding a client session.
+     * This must be called before adding a client session. This corresponds
+     * to the number of incoming connections to RpcSession objects in the
+     * server, which will correspond to the number of outgoing connections
+     * in client RpcSession objects.
      *
      * If this is not specified, this will be a single-threaded server.
      *
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 40faf2c..0750ccf 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -54,8 +54,6 @@
  */
 class RpcSession final : public virtual RefBase {
 public:
-    static constexpr size_t kDefaultMaxOutgoingThreads = 10;
-
     // Create an RpcSession with default configuration (raw sockets).
     static sp<RpcSession> make();
 
@@ -67,26 +65,30 @@
     /**
      * Set the maximum number of incoming threads allowed to be made (for things like callbacks).
      * By default, this is 0. This must be called before setting up this connection as a client.
-     * Server sessions will inherits this value from RpcServer.
+     * Server sessions will inherits this value from RpcServer. Each thread will serve a
+     * connection to the remote RpcSession.
      *
      * If this is called, 'shutdown' on this session must also be called.
      * Otherwise, a threadpool will leak.
      *
-     * TODO(b/189955605): start these dynamically
+     * TODO(b/189955605): start these lazily - currently all are started
      */
     void setMaxIncomingThreads(size_t threads);
     size_t getMaxIncomingThreads();
 
     /**
-     * Set the maximum number of outgoing threads allowed to be made.
-     * By default, this is |kDefaultMaxOutgoingThreads|. This must be called before setting up this
-     * connection as a client.
+     * Set the maximum number of outgoing connections allowed to be made.
+     * By default, this is |kDefaultMaxOutgoingConnections|. This must be called before setting up
+     * this connection as a client.
      *
-     * This limits the number of outgoing threads on top of the remote peer setting. This RpcSession
-     * will only instantiate |min(maxOutgoingThreads, remoteMaxThreads)| outgoing threads, where
-     * |remoteMaxThreads| can be retrieved from the remote peer via |getRemoteMaxThreads()|.
+     * For an RpcSession client, if you are connecting to a server which starts N threads,
+     * then this must be set to >= N. If you set the maximum number of outgoing connections
+     * to 1, but the server requests 10, then it would be considered an error. If you set a
+     * maximum number of connections to 10, and the server requests 1, then only 1 will be
+     * created. This API is used to limit the amount of resources a server can request you
+     * create.
      */
-    void setMaxOutgoingThreads(size_t threads);
+    void setMaxOutgoingConnections(size_t connections);
     size_t getMaxOutgoingThreads();
 
     /**
@@ -219,6 +221,8 @@
     friend RpcState;
     explicit RpcSession(std::unique_ptr<RpcTransportCtx> ctx);
 
+    static constexpr size_t kDefaultMaxOutgoingConnections = 10;
+
     // internal version of setProtocolVersion that
     // optionally skips the mStartedSetup check
     [[nodiscard]] bool setProtocolVersionInternal(uint32_t version, bool checkStarted);
@@ -368,7 +372,7 @@
 
     bool mStartedSetup = false;
     size_t mMaxIncomingThreads = 0;
-    size_t mMaxOutgoingThreads = kDefaultMaxOutgoingThreads;
+    size_t mMaxOutgoingConnections = kDefaultMaxOutgoingConnections;
     std::optional<uint32_t> mProtocolVersion;
     FileDescriptorTransportMode mFileDescriptorTransportMode = FileDescriptorTransportMode::NONE;
 
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 42d226b..a157792 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -126,11 +126,11 @@
 void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session,
                                                 ARpcSession_FileDescriptorTransportMode mode);
 
-// Sets the maximum number of incoming threads.
+// Sets the maximum number of incoming threads, to service connections.
 void ARpcSession_setMaxIncomingThreads(ARpcSession* session, size_t threads);
 
-// Sets the maximum number of outgoing threads.
-void ARpcSession_setMaxOutgoingThreads(ARpcSession* session, size_t threads);
+// Sets the maximum number of outgoing connections.
+void ARpcSession_setMaxOutgoingConnections(ARpcSession* session, size_t connections);
 
 // Decrements the refcount of the underlying RpcSession object.
 void ARpcSession_free(ARpcSession* session);
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index daff8c1..a167f23 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -265,8 +265,8 @@
     session->setMaxIncomingThreads(threads);
 }
 
-void ARpcSession_setMaxOutgoingThreads(ARpcSession* handle, size_t threads) {
+void ARpcSession_setMaxOutgoingConnections(ARpcSession* handle, size_t connections) {
     auto session = handleToStrongPointer<RpcSession>(handle);
-    session->setMaxOutgoingThreads(threads);
+    session->setMaxOutgoingConnections(connections);
 }
 }
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index f68612c..d833b83 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -26,11 +26,11 @@
 
 #pragma once
 
+#include <android/binder_status.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <sys/cdefs.h>
-
-#include <android/binder_status.h>
+#include <uchar.h>
 
 struct AIBinder;
 typedef struct AIBinder AIBinder;
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 86d5ed2..43159d8 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -22,6 +22,16 @@
 
 __BEGIN_DECLS
 
+enum AServiceManager_AddServiceFlag : uint32_t {
+    /**
+     * This allows processes with AID_ISOLATED to get the binder of the service added.
+     *
+     * Services with methods that perform file IO, web socket creation or ways to egress data must
+     * not be added with this flag for privacy concerns.
+     */
+    ADD_SERVICE_ALLOW_ISOLATED = 1,
+};
+
 /**
  * This registers the service with the default service manager under this instance name. This does
  * not take ownership of binder.
@@ -46,12 +56,13 @@
  *
  * \param binder object to register globally with the service manager.
  * \param instance identifier of the service. This will be used to lookup the service.
- * \param allowIsolated allows if this service can be isolated.
+ * \param flag an AServiceManager_AddServiceFlag enum to denote how the service should be added.
  *
  * \return EX_NONE on success.
  */
-__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addServiceWithAllowIsolated(
-        AIBinder* binder, const char* instance, bool allowIsolated) __INTRODUCED_IN(34);
+__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addServiceWithFlag(
+        AIBinder* binder, const char* instance, const AServiceManager_AddServiceFlag flag)
+        __INTRODUCED_IN(34);
 
 /**
  * Gets a binder object with this specific instance name. Will return nullptr immediately if the
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 5f2f617..1078fb2 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -158,12 +158,12 @@
     AServiceManager_getUpdatableApexName; # systemapi
     AServiceManager_registerForServiceNotifications; # systemapi llndk
     AServiceManager_NotificationRegistration_delete; # systemapi llndk
+    AServiceManager_addServiceWithFlag; # systemapi llndk
 };
 
 LIBBINDER_NDK_PLATFORM {
   global:
     AParcel_getAllowFds;
-    AServiceManager_addServiceWithAllowIsolated;
     extern "C++" {
         AIBinder_fromPlatformBinder*;
         AIBinder_toPlatformBinder*;
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 2763ddb..84da459 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -42,14 +42,15 @@
     return PruneException(exception);
 }
 
-binder_exception_t AServiceManager_addServiceWithAllowIsolated(AIBinder* binder,
-                                                               const char* instance,
-                                                               bool allowIsolated) {
+binder_exception_t AServiceManager_addServiceWithFlag(AIBinder* binder, const char* instance,
+                                                      const AServiceManager_AddServiceFlag flag) {
     if (binder == nullptr || instance == nullptr) {
         return EX_ILLEGAL_ARGUMENT;
     }
 
     sp<IServiceManager> sm = defaultServiceManager();
+
+    bool allowIsolated = flag & AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED;
     status_t exception = sm->addService(String16(instance), binder->getBinder(), allowIsolated);
     return PruneException(exception);
 }
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 5b2532a..882f1d6 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -52,7 +52,7 @@
 constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
 constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
 
-constexpr unsigned int kShutdownWaitTime = 10;
+constexpr unsigned int kShutdownWaitTime = 11;
 constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
 
 class MyTestFoo : public IFoo {
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index afd414a..d36ebac 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -21,6 +21,7 @@
     ],
     host_supported: true,
     vendor_available: true,
+    product_available: true,
     target: {
         darwin: {
             enabled: false,
@@ -72,6 +73,7 @@
     ],
     host_supported: true,
     vendor_available: true,
+    product_available: true,
     target: {
         darwin: {
             enabled: false,
@@ -129,6 +131,7 @@
     ],
     host_supported: true,
     vendor_available: true,
+    product_available: true,
 
     // Currently necessary for host builds
     // TODO(b/31559095): bionic on host should define this
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index da9797b..0067a20 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -26,6 +26,7 @@
     visibility: [
         "//device/google/cuttlefish/shared/minidroid/sample",
         "//packages/modules/Virtualization:__subpackages__",
+        "//system/software_defined_vehicle:__subpackages__",
     ],
     apex_available: [
         "//apex_available:platform",
diff --git a/libs/binder/rust/rpcbinder/src/session.rs b/libs/binder/rust/rpcbinder/src/session.rs
index 0b517cf..28c5390 100644
--- a/libs/binder/rust/rpcbinder/src/session.rs
+++ b/libs/binder/rust/rpcbinder/src/session.rs
@@ -75,11 +75,14 @@
         };
     }
 
-    /// Sets the maximum number of outgoing threads.
-    pub fn set_max_outgoing_threads(&self, threads: usize) {
+    /// Sets the maximum number of outgoing connections.
+    pub fn set_max_outgoing_connections(&self, connections: usize) {
         // SAFETY - Only passes the 'self' pointer as an opaque handle.
         unsafe {
-            binder_rpc_unstable_bindgen::ARpcSession_setMaxOutgoingThreads(self.as_ptr(), threads)
+            binder_rpc_unstable_bindgen::ARpcSession_setMaxOutgoingConnections(
+                self.as_ptr(),
+                connections,
+            )
         };
     }
 
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 6f686fb..5557168 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -209,8 +209,8 @@
     }
 
     /// Mark this binder object with local stability, which is vendor if we are
-    /// building for the VNDK and system otherwise.
-    #[cfg(any(vendor_ndk, android_vndk))]
+    /// building for android_vendor and system otherwise.
+    #[cfg(android_vendor)]
     fn mark_local_stability(&mut self) {
         unsafe {
             // Safety: Self always contains a valid `AIBinder` pointer, so
@@ -220,8 +220,8 @@
     }
 
     /// Mark this binder object with local stability, which is vendor if we are
-    /// building for the VNDK and system otherwise.
-    #[cfg(not(any(vendor_ndk, android_vndk)))]
+    /// building for android_vendor and system otherwise.
+    #[cfg(not(android_vendor))]
     fn mark_local_stability(&mut self) {
         unsafe {
             // Safety: Self always contains a valid `AIBinder` pointer, so
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2a4fc48..0f0d64a 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -138,7 +138,6 @@
 
 aidl_interface {
     name: "binderRpcTestIface",
-    vendor_available: true,
     host_supported: true,
     unstable: true,
     srcs: [
@@ -159,7 +158,6 @@
 
 cc_library_static {
     name: "libbinder_tls_test_utils",
-    vendor_available: true,
     host_supported: true,
     target: {
         darwin: {
@@ -213,7 +211,6 @@
     defaults: [
         "binderRpcTest_common_defaults",
     ],
-    vendor_available: true,
     gtest: false,
     auto_gen_config: false,
     srcs: [
@@ -224,18 +221,10 @@
 
 cc_defaults {
     name: "binderRpcTest_defaults",
-    vendor_available: true,
     target: {
         android: {
             test_suites: ["vts"],
         },
-
-        vendor: {
-            shared_libs: [
-                "libbinder_trusty",
-                "libtrusty",
-            ],
-        },
     },
     defaults: [
         "binderRpcTest_common_defaults",
@@ -397,11 +386,6 @@
 
 cc_test {
     name: "binderRpcTest",
-    // TODO(b/269799024)
-    test_options: {
-        unit_test: false,
-    },
-
     defaults: [
         "binderRpcTest_defaults",
         "binderRpcTest_shared_defaults",
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index a3ed571..1164767 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -80,4 +80,8 @@
     // get queued.
     oneway void blockingSendFdOneway(in ParcelFileDescriptor fd);
     ParcelFileDescriptor blockingRecvFd();
+
+    // Same as blockingSendFdOneway, but with integers.
+    oneway void blockingSendIntOneway(int n);
+    int blockingRecvInt();
 }
diff --git a/libs/binder/tests/binderHostDeviceTest.cpp b/libs/binder/tests/binderHostDeviceTest.cpp
index 464da60..77a5fa8 100644
--- a/libs/binder/tests/binderHostDeviceTest.cpp
+++ b/libs/binder/tests/binderHostDeviceTest.cpp
@@ -66,7 +66,7 @@
 void initHostRpcServiceManagerOnce() {
     static std::once_flag gSmOnce;
     std::call_once(gSmOnce, [] {
-        setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingThreads = 1}));
+        setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingConnections = 1}));
     });
 }
 
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 955c650..8974ad7 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -507,7 +507,13 @@
     }
 
     EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, true, 0));
-    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, true, 0));
+
+    // b/268232063 - succeeds ~0.08% of the time
+    {
+        auto ret = IPCThreadState::self()->freeze(pid, true, 0);
+        EXPECT_TRUE(ret == -EAGAIN || ret == OK);
+    }
+
     EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, true, 1000));
     EXPECT_EQ(FAILED_TRANSACTION, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
 
@@ -1370,7 +1376,7 @@
         }));
     }
 
-    data.writeInt32(100);
+    data.writeInt32(500);
     // Give a chance for all threads to be used
     EXPECT_THAT(server->transact(BINDER_LIB_TEST_UNLOCK_AFTER_MS, data, &reply), NO_ERROR);
 
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 84c93dd..9f54087 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -129,7 +129,7 @@
 static std::string allocateSocketAddress() {
     static size_t id = 0;
     std::string temp = getenv("TMPDIR") ?: "/tmp";
-    auto ret = temp + "/binderRpcTest_" + std::to_string(id++);
+    auto ret = temp + "/binderRpcTest_" + std::to_string(getpid()) + "_" + std::to_string(id++);
     unlink(ret.c_str());
     return ret;
 };
@@ -237,9 +237,13 @@
             std::to_string(clientVersion) + "_serverV" + std::to_string(serverVersion);
     if (singleThreaded) {
         ret += "_single_threaded";
+    } else {
+        ret += "_multi_threaded";
     }
     if (noKernel) {
         ret += "_no_kernel";
+    } else {
+        ret += "_with_kernel";
     }
     return ret;
 }
@@ -350,7 +354,7 @@
     for (const auto& session : sessions) {
         CHECK(session->setProtocolVersion(clientVersion));
         session->setMaxIncomingThreads(options.numIncomingConnections);
-        session->setMaxOutgoingThreads(options.numOutgoingConnections);
+        session->setMaxOutgoingConnections(options.numOutgoingConnections);
         session->setFileDescriptorTransportMode(options.clientFileDescriptorTransportMode);
 
         switch (socketType) {
@@ -435,8 +439,7 @@
     for (auto& t : ts) t.join();
 }
 
-static void testThreadPoolOverSaturated(sp<IBinderRpcTest> iface, size_t numCalls,
-                                        size_t sleepMs = 500) {
+static void testThreadPoolOverSaturated(sp<IBinderRpcTest> iface, size_t numCalls, size_t sleepMs) {
     size_t epochMsBefore = epochMillis();
 
     std::vector<std::thread> ts;
@@ -462,7 +465,7 @@
     constexpr size_t kNumThreads = 10;
     constexpr size_t kNumCalls = kNumThreads + 3;
     auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
-    testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
+    testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 250 /*ms*/);
 }
 
 TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
@@ -475,7 +478,7 @@
     constexpr size_t kNumCalls = kNumOutgoingConnections + 3;
     auto proc = createRpcTestSocketServerProcess(
             {.numThreads = kNumThreads, .numOutgoingConnections = kNumOutgoingConnections});
-    testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
+    testThreadPoolOverSaturated(proc.rootIface, kNumCalls, 250 /*ms*/);
 }
 
 TEST_P(BinderRpc, ThreadingStressTest) {
@@ -483,9 +486,9 @@
         GTEST_SKIP() << "This test requires multiple threads";
     }
 
-    constexpr size_t kNumClientThreads = 10;
-    constexpr size_t kNumServerThreads = 10;
-    constexpr size_t kNumCalls = 100;
+    constexpr size_t kNumClientThreads = 5;
+    constexpr size_t kNumServerThreads = 5;
+    constexpr size_t kNumCalls = 50;
 
     auto proc = createRpcTestSocketServerProcess({.numThreads = kNumServerThreads});
 
@@ -544,6 +547,8 @@
         GTEST_SKIP() << "This test requires multiple threads";
     }
 
+    constexpr size_t kNumServerThreads = 3;
+
     // This test forces a oneway transaction to be queued by issuing two
     // `blockingSendFdOneway` calls, then drains the queue by issuing two
     // `blockingRecvFd` calls.
@@ -552,7 +557,7 @@
     // https://developer.android.com/reference/android/os/IBinder#FLAG_ONEWAY
 
     auto proc = createRpcTestSocketServerProcess({
-            .numThreads = 3,
+            .numThreads = kNumServerThreads,
             .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
             .serverSupportedFileDescriptorTransportModes =
                     {RpcSession::FileDescriptorTransportMode::UNIX},
@@ -573,6 +578,8 @@
     EXPECT_OK(proc.rootIface->blockingRecvFd(&fdB));
     CHECK(android::base::ReadFdToString(fdB.get(), &result));
     EXPECT_EQ(result, "b");
+
+    saturateThreadPool(kNumServerThreads, proc.rootIface);
 }
 
 TEST_P(BinderRpc, OnewayCallQueueing) {
@@ -580,30 +587,22 @@
         GTEST_SKIP() << "This test requires multiple threads";
     }
 
-    constexpr size_t kNumSleeps = 10;
+    constexpr size_t kNumQueued = 10;
     constexpr size_t kNumExtraServerThreads = 4;
-    constexpr size_t kSleepMs = 50;
 
     // make sure calls to the same object happen on the same thread
     auto proc = createRpcTestSocketServerProcess({.numThreads = 1 + kNumExtraServerThreads});
 
-    EXPECT_OK(proc.rootIface->lock());
-
-    size_t epochMsBefore = epochMillis();
-
-    // all these *Async commands should be queued on the server sequentially,
+    // all these *Oneway commands should be queued on the server sequentially,
     // even though there are multiple threads.
-    for (size_t i = 0; i + 1 < kNumSleeps; i++) {
-        proc.rootIface->sleepMsAsync(kSleepMs);
+    for (size_t i = 0; i + 1 < kNumQueued; i++) {
+        proc.rootIface->blockingSendIntOneway(i);
     }
-    EXPECT_OK(proc.rootIface->unlockInMsAsync(kSleepMs));
-
-    // this can only return once the final async call has unlocked
-    EXPECT_OK(proc.rootIface->lockUnlock());
-
-    size_t epochMsAfter = epochMillis();
-
-    EXPECT_GE(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps);
+    for (size_t i = 0; i + 1 < kNumQueued; i++) {
+        int n;
+        proc.rootIface->blockingRecvInt(&n);
+        EXPECT_EQ(n, i);
+    }
 
     saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
 }
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index a467ee3..d129661 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -445,6 +445,12 @@
     Status blockingRecvFd(android::os::ParcelFileDescriptor* /*fd*/) override {
         return Status::fromStatusT(UNKNOWN_TRANSACTION);
     }
+
+    Status blockingSendIntOneway(int /*n*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+
+    Status blockingRecvInt(int* /*n*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
 };
 
 } // namespace android
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index 714f063..ca5a117 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -83,9 +83,23 @@
         fd->reset(mFdChannel.read());
         return Status::ok();
     }
+
+    HandoffChannel<int> mIntChannel;
+
+    Status blockingSendIntOneway(int n) override {
+        mIntChannel.write(n);
+        return Status::ok();
+    }
+
+    Status blockingRecvInt(int* n) override {
+        *n = mIntChannel.read();
+        return Status::ok();
+    }
 };
 
-int main(int argc, const char* argv[]) {
+int main(int argc, char* argv[]) {
+    android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter);
+
     LOG_ALWAYS_FATAL_IF(argc != 3, "Invalid number of arguments: %d", argc);
     base::unique_fd writeEnd(atoi(argv[1]));
     base::unique_fd readEnd(atoi(argv[2]));
diff --git a/libs/binder/tests/binderRpcTestTrusty.cpp b/libs/binder/tests/binderRpcTestTrusty.cpp
index b3bb5eb..63b56a3 100644
--- a/libs/binder/tests/binderRpcTestTrusty.cpp
+++ b/libs/binder/tests/binderRpcTestTrusty.cpp
@@ -45,9 +45,13 @@
             std::to_string(serverVersion);
     if (singleThreaded) {
         ret += "_single_threaded";
+    } else {
+        ret += "_multi_threaded";
     }
     if (noKernel) {
         ret += "_no_kernel";
+    } else {
+        ret += "_with_kernel";
     }
     return ret;
 }
@@ -71,7 +75,7 @@
         auto session = android::RpcSession::make(std::move(factory));
 
         EXPECT_TRUE(session->setProtocolVersion(clientVersion));
-        session->setMaxOutgoingThreads(options.numOutgoingConnections);
+        session->setMaxOutgoingConnections(options.numOutgoingConnections);
         session->setFileDescriptorTransportMode(options.clientFileDescriptorTransportMode);
 
         status = session->setupPreconnectedClient({}, [&]() {
diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
index 8ea948c..a881582 100644
--- a/libs/binder/tests/unit_fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -104,3 +104,42 @@
     defaults: ["binder_fuzz_defaults"],
     srcs: ["MemoryDealerFuzz.cpp"],
 }
+
+cc_fuzz {
+    name: "binder_recordedTransactionFileFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["RecordedTransactionFileFuzz.cpp"],
+    corpus: [
+        "recorded_transaction_corpus/*",
+    ],
+}
+
+cc_fuzz {
+    name: "binder_recordedTransactionFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["RecordedTransactionFuzz.cpp"],
+    target: {
+        android: {
+            shared_libs: [
+                "libcutils",
+                "libutils",
+                "libbase",
+                "libbinder",
+            ],
+            static_libs: ["libbinder_random_parcel"],
+        },
+        host: {
+            static_libs: [
+                "libcutils",
+                "liblog",
+                "libutils",
+                "libbase",
+                "libbinder",
+                "libbinder_random_parcel",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp b/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp
new file mode 100644
index 0000000..73790fa
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/RecordedTransactionFileFuzz.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include <android-base/macros.h>
+#include <binder/RecordedTransaction.h>
+#include <filesystem>
+
+#include "fuzzer/FuzzedDataProvider.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    std::FILE* intermediateFile = std::tmpfile();
+    fwrite(data, sizeof(uint8_t), size, intermediateFile);
+    rewind(intermediateFile);
+    int fileNumber = fileno(intermediateFile);
+
+    android::base::unique_fd fd(fileNumber);
+
+    auto transaction = android::binder::debug::RecordedTransaction::fromFile(fd);
+
+    std::fclose(intermediateFile);
+
+    if (transaction.has_value()) {
+        intermediateFile = std::tmpfile();
+
+        android::base::unique_fd fdForWriting(fileno(intermediateFile));
+        auto writeStatus ATTRIBUTE_UNUSED = transaction.value().dumpToFile(fdForWriting);
+
+        std::fclose(intermediateFile);
+    }
+
+    return 0;
+}
diff --git a/libs/binder/tests/unit_fuzzers/RecordedTransactionFuzz.cpp b/libs/binder/tests/unit_fuzzers/RecordedTransactionFuzz.cpp
new file mode 100644
index 0000000..943fb9f
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/RecordedTransactionFuzz.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include <android-base/macros.h>
+#include <binder/RecordedTransaction.h>
+#include <fuzzbinder/random_parcel.h>
+#include <filesystem>
+#include <string>
+
+#include "fuzzer/FuzzedDataProvider.h"
+
+using android::fillRandomParcel;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+
+    android::String16 interfaceName =
+            android::String16(provider.ConsumeRandomLengthString().c_str());
+
+    uint32_t code = provider.ConsumeIntegral<uint32_t>();
+    uint32_t flags = provider.ConsumeIntegral<uint32_t>();
+    time_t sec = provider.ConsumeIntegral<time_t>();
+    long nsec = provider.ConsumeIntegral<long>();
+    timespec timestamp = {.tv_sec = sec, .tv_nsec = nsec};
+    android::status_t transactionStatus = provider.ConsumeIntegral<android::status_t>();
+
+    std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(
+            provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
+
+    // same options so that FDs and binders could be shared in both Parcels
+    android::RandomParcelOptions options;
+
+    android::Parcel p0, p1;
+    fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options);
+    fillRandomParcel(&p1, std::move(provider), &options);
+
+    auto transaction =
+            android::binder::debug::RecordedTransaction::fromDetails(interfaceName, code, flags,
+                                                                     timestamp, p0, p1,
+                                                                     transactionStatus);
+
+    if (transaction.has_value()) {
+        std::FILE* intermediateFile = std::tmpfile();
+        android::base::unique_fd fdForWriting(fileno(intermediateFile));
+        auto writeStatus ATTRIBUTE_UNUSED = transaction.value().dumpToFile(fdForWriting);
+
+        std::fclose(intermediateFile);
+    }
+
+    return 0;
+}
diff --git a/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/power_recording b/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/power_recording
new file mode 100644
index 0000000..79442078
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/power_recording
Binary files differ
diff --git a/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/recorded_binder_transaction b/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/recorded_binder_transaction
new file mode 100644
index 0000000..658addb
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/recorded_transaction_corpus/recorded_binder_transaction
Binary files differ
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp
index 29924ff..96dcce1 100644
--- a/libs/fakeservicemanager/Android.bp
+++ b/libs/fakeservicemanager/Android.bp
@@ -11,7 +11,7 @@
     name: "fakeservicemanager_defaults",
     host_supported: true,
     srcs: [
-        "ServiceManager.cpp",
+        "FakeServiceManager.cpp",
     ],
 
     shared_libs: [
@@ -28,7 +28,7 @@
 cc_library {
     name: "libfakeservicemanager",
     defaults: ["fakeservicemanager_defaults"],
-    export_include_dirs: ["include/fakeservicemanager"],
+    export_include_dirs: ["include"],
 }
 
 cc_test_host {
@@ -38,5 +38,5 @@
         "test_sm.cpp",
     ],
     static_libs: ["libgmock"],
-    local_include_dirs: ["include/fakeservicemanager"],
+    local_include_dirs: ["include"],
 }
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/FakeServiceManager.cpp
similarity index 66%
rename from libs/fakeservicemanager/ServiceManager.cpp
rename to libs/fakeservicemanager/FakeServiceManager.cpp
index 1109ad8..3272bbc 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/FakeServiceManager.cpp
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-#include "ServiceManager.h"
+#include "fakeservicemanager/FakeServiceManager.h"
 
 namespace android {
 
-ServiceManager::ServiceManager() {}
+FakeServiceManager::FakeServiceManager() {}
 
-sp<IBinder> ServiceManager::getService( const String16& name) const {
+sp<IBinder> FakeServiceManager::getService( const String16& name) const {
     // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
     return checkService(name);
 }
 
-sp<IBinder> ServiceManager::checkService( const String16& name) const {
+sp<IBinder> FakeServiceManager::checkService( const String16& name) const {
     auto it = mNameToService.find(name);
     if (it == mNameToService.end()) {
         return nullptr;
@@ -33,7 +33,7 @@
     return it->second;
 }
 
-status_t ServiceManager::addService(const String16& name, const sp<IBinder>& service,
+status_t FakeServiceManager::addService(const String16& name, const sp<IBinder>& service,
                                 bool /*allowIsolated*/,
                                 int /*dumpsysFlags*/) {
     if (service == nullptr) {
@@ -43,7 +43,7 @@
     return NO_ERROR;
 }
 
-Vector<String16> ServiceManager::listServices(int /*dumpsysFlags*/) {
+Vector<String16> FakeServiceManager::listServices(int /*dumpsysFlags*/) {
     Vector<String16> services;
     for (auto const& [name, service] : mNameToService) {
         (void) service;
@@ -52,19 +52,19 @@
   return services;
 }
 
-IBinder* ServiceManager::onAsBinder() {
+IBinder* FakeServiceManager::onAsBinder() {
     return nullptr;
 }
 
-sp<IBinder> ServiceManager::waitForService(const String16& name) {
+sp<IBinder> FakeServiceManager::waitForService(const String16& name) {
     return checkService(name);
 }
 
-bool ServiceManager::isDeclared(const String16& name) {
+bool FakeServiceManager::isDeclared(const String16& name) {
     return mNameToService.find(name) != mNameToService.end();
 }
 
-Vector<String16> ServiceManager::getDeclaredInstances(const String16& name) {
+Vector<String16> FakeServiceManager::getDeclaredInstances(const String16& name) {
     Vector<String16> out;
     const String16 prefix = name + String16("/");
     for (const auto& [registeredName, service] : mNameToService) {
@@ -76,38 +76,38 @@
     return out;
 }
 
-std::optional<String16> ServiceManager::updatableViaApex(const String16& name) {
+std::optional<String16> FakeServiceManager::updatableViaApex(const String16& name) {
     (void)name;
     return std::nullopt;
 }
 
-Vector<String16> ServiceManager::getUpdatableNames(const String16& apexName) {
+Vector<String16> FakeServiceManager::getUpdatableNames(const String16& apexName) {
     (void)apexName;
     return {};
 }
 
-std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo(
+std::optional<IServiceManager::ConnectionInfo> FakeServiceManager::getConnectionInfo(
         const String16& name) {
     (void)name;
     return std::nullopt;
 }
 
-status_t ServiceManager::registerForNotifications(const String16&,
+status_t FakeServiceManager::registerForNotifications(const String16&,
                                                   const sp<LocalRegistrationCallback>&) {
     return INVALID_OPERATION;
 }
 
-status_t ServiceManager::unregisterForNotifications(const String16&,
+status_t FakeServiceManager::unregisterForNotifications(const String16&,
                                                 const sp<LocalRegistrationCallback>&) {
     return INVALID_OPERATION;
 }
 
-std::vector<IServiceManager::ServiceDebugInfo> ServiceManager::getServiceDebugInfo() {
+std::vector<IServiceManager::ServiceDebugInfo> FakeServiceManager::getServiceDebugInfo() {
     std::vector<IServiceManager::ServiceDebugInfo> ret;
     return ret;
 }
 
-void ServiceManager::clear() {
+void FakeServiceManager::clear() {
     mNameToService.clear();
 }
 }  // namespace android
diff --git a/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
similarity index 96%
rename from libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h
rename to libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
index ba6bb7d..97add24 100644
--- a/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
@@ -28,9 +28,9 @@
  * A local host simple implementation of IServiceManager, that does not
  * communicate over binder.
 */
-class ServiceManager : public IServiceManager {
+class FakeServiceManager : public IServiceManager {
 public:
-    ServiceManager();
+    FakeServiceManager();
 
     sp<IBinder> getService( const String16& name) const override;
 
diff --git a/libs/fakeservicemanager/test_sm.cpp b/libs/fakeservicemanager/test_sm.cpp
index 8682c1c..6fc21c6 100644
--- a/libs/fakeservicemanager/test_sm.cpp
+++ b/libs/fakeservicemanager/test_sm.cpp
@@ -21,14 +21,14 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 
-#include "ServiceManager.h"
+#include "fakeservicemanager/FakeServiceManager.h"
 
 using android::sp;
 using android::BBinder;
 using android::IBinder;
 using android::OK;
 using android::status_t;
-using android::ServiceManager;
+using android::FakeServiceManager;
 using android::String16;
 using android::IServiceManager;
 using testing::ElementsAre;
@@ -45,19 +45,19 @@
 }
 
 TEST(AddService, HappyHappy) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
 }
 
 TEST(AddService, SadNullBinder) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     EXPECT_EQ(sm->addService(String16("foo"), nullptr, false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), android::UNEXPECTED_NULL);
 }
 
 TEST(AddService, HappyOverExistingService) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
     EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
@@ -65,7 +65,7 @@
 }
 
 TEST(AddService, HappyClearAddedService) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
     EXPECT_NE(sm->getService(String16("foo")), nullptr);
@@ -74,7 +74,7 @@
 }
 
 TEST(GetService, HappyHappy) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     sp<IBinder> service = getBinder();
 
     EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
@@ -84,13 +84,13 @@
 }
 
 TEST(GetService, NonExistant) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
 
     EXPECT_EQ(sm->getService(String16("foo")), nullptr);
 }
 
 TEST(ListServices, AllServices) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
 
     EXPECT_EQ(sm->addService(String16("sd"), getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK);
@@ -109,13 +109,13 @@
 }
 
 TEST(WaitForService, NonExistant) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
 
     EXPECT_EQ(sm->waitForService(String16("foo")), nullptr);
 }
 
 TEST(WaitForService, HappyHappy) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     sp<IBinder> service = getBinder();
 
     EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
@@ -125,13 +125,13 @@
 }
 
 TEST(IsDeclared, NonExistant) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
 
     EXPECT_FALSE(sm->isDeclared(String16("foo")));
 }
 
 TEST(IsDeclared, HappyHappy) {
-    auto sm = new ServiceManager();
+    auto sm = new FakeServiceManager();
     sp<IBinder> service = getBinder();
 
     EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/,
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index c010a2e..09422d3 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -10,9 +10,6 @@
 cc_test {
     name: "ftl_test",
     test_suites: ["device-tests"],
-    sanitize: {
-        address: true,
-    },
     srcs: [
         "cast_test.cpp",
         "concat_test.cpp",
diff --git a/libs/ftl/TEST_MAPPING b/libs/ftl/TEST_MAPPING
new file mode 100644
index 0000000..ec0c671
--- /dev/null
+++ b/libs/ftl/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "ftl_test"
+    }
+  ],
+  "hwasan-presubmit": [
+    {
+      "name": "ftl_test"
+    }
+  ]
+}
diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS
index 347c4e0..1db8cbe 100644
--- a/libs/graphicsenv/OWNERS
+++ b/libs/graphicsenv/OWNERS
@@ -1,10 +1,4 @@
-abdolrashidi@google.com
-cclao@google.com
 chrisforbes@google.com
 cnorthrop@google.com
 ianelliott@google.com
-lfy@google.com
 lpy@google.com
-romanl@google.com
-vantablack@google.com
-yuxinhu@google.com
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 1bfe462..198908d 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -16,17 +16,59 @@
 
 #define LOG_TAG "Surface"
 
-#include <gui/view/Surface.h>
-
+#include <android/binder_libbinder.h>
+#include <android/binder_parcel.h>
+#include <android/native_window.h>
 #include <binder/Parcel.h>
-
-#include <utils/Log.h>
-
 #include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/view/Surface.h>
+#include <system/window.h>
+#include <utils/Log.h>
 
 namespace android {
 namespace view {
 
+// Since this is a parcelable utility and we want to keep the wire format stable, only build this
+// when building the system libgui to detect any issues loading the wrong libgui from
+// libnativewindow
+
+#if (!defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__))
+
+extern "C" status_t android_view_Surface_writeToParcel(ANativeWindow* _Nonnull window,
+                                                       Parcel* _Nonnull parcel) {
+    int value;
+    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
+    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
+        ALOGE("Error: ANativeWindow is not backed by Surface");
+        return STATUS_BAD_VALUE;
+    }
+    // Use a android::view::Surface to parcelize the window
+    android::view::Surface shimSurface;
+    shimSurface.graphicBufferProducer = android::Surface::getIGraphicBufferProducer(window);
+    shimSurface.surfaceControlHandle = android::Surface::getSurfaceControlHandle(window);
+    return shimSurface.writeToParcel(parcel);
+}
+
+extern "C" status_t android_view_Surface_readFromParcel(
+        const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
+    // Use a android::view::Surface to unparcel the window
+    android::view::Surface shimSurface;
+    status_t ret = shimSurface.readFromParcel(parcel);
+    if (ret != OK) {
+        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
+        return STATUS_BAD_VALUE;
+    }
+    auto surface = sp<android::Surface>::make(shimSurface.graphicBufferProducer, false,
+                                              shimSurface.surfaceControlHandle);
+    ANativeWindow* anw = surface.get();
+    ANativeWindow_acquire(anw);
+    *outWindow = anw;
+    return STATUS_OK;
+}
+
+#endif
+
 status_t Surface::writeToParcel(Parcel* parcel) const {
     return writeToParcel(parcel, false);
 }
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 2b7483d..2581668 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -137,10 +137,23 @@
 
 // --- InputEvent ---
 
+// Due to precision limitations when working with floating points, transforming - namely
+// scaling - floating points can lead to minute errors. We round transformed values to approximately
+// three decimal places so that values like 0.99997 show up as 1.0.
+inline float roundTransformedCoords(float val) {
+    // Use a power to two to approximate three decimal places to potentially reduce some cycles.
+    // This should be at least as precise as MotionEvent::ROUNDING_PRECISION.
+    return std::round(val * 1024.f) / 1024.f;
+}
+
+inline vec2 roundTransformedCoords(vec2 p) {
+    return {roundTransformedCoords(p.x), roundTransformedCoords(p.y)};
+}
+
 vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) {
     const vec2 transformedXy = transform.transform(xy);
     const vec2 transformedOrigin = transform.transform(0, 0);
-    return transformedXy - transformedOrigin;
+    return roundTransformedCoords(transformedXy - transformedOrigin);
 }
 
 const char* inputEventTypeToString(int32_t type) {
@@ -548,12 +561,12 @@
 
 float MotionEvent::getXCursorPosition() const {
     vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition());
-    return vals.x;
+    return roundTransformedCoords(vals.x);
 }
 
 float MotionEvent::getYCursorPosition() const {
     vec2 vals = mTransform.transform(getRawXCursorPosition(), getRawYCursorPosition());
-    return vals.y;
+    return roundTransformedCoords(vals.y);
 }
 
 void MotionEvent::setCursorPosition(float x, float y) {
@@ -875,7 +888,7 @@
 static inline vec2 calculateTransformedXYUnchecked(uint32_t source, const ui::Transform& transform,
                                                    const vec2& xy) {
     return shouldDisregardOffset(source) ? transformWithoutTranslation(transform, xy)
-                                         : transform.transform(xy);
+                                         : roundTransformedCoords(transform.transform(xy));
 }
 
 vec2 MotionEvent::calculateTransformedXY(uint32_t source, const ui::Transform& transform,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 4b31246..597b389 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -29,6 +29,8 @@
 // Default display id.
 static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
 
+static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
+
 class BaseTest : public testing::Test {
 protected:
     static constexpr std::array<uint8_t, 32> HMAC = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
@@ -231,95 +233,107 @@
     static constexpr float RAW_X_OFFSET = 12;
     static constexpr float RAW_Y_OFFSET = -41.1;
 
+    void SetUp() override;
+
     int32_t mId;
     ui::Transform mTransform;
     ui::Transform mRawTransform;
+    PointerProperties mPointerProperties[2];
+    struct Sample {
+        PointerCoords pointerCoords[2];
+    };
+    std::array<Sample, 3> mSamples{};
 
     void initializeEventWithHistory(MotionEvent* event);
     void assertEqualsEventWithHistory(const MotionEvent* event);
 };
 
-void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
+void MotionEventTest::SetUp() {
     mId = InputEvent::nextId();
     mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1});
     mRawTransform.set({RAW_X_SCALE, 0, RAW_X_OFFSET, 0, RAW_Y_SCALE, RAW_Y_OFFSET, 0, 0, 1});
 
-    PointerProperties pointerProperties[2];
-    pointerProperties[0].clear();
-    pointerProperties[0].id = 1;
-    pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-    pointerProperties[1].clear();
-    pointerProperties[1].id = 2;
-    pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+    mPointerProperties[0].clear();
+    mPointerProperties[0].id = 1;
+    mPointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+    mPointerProperties[1].clear();
+    mPointerProperties[1].id = 2;
+    mPointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
 
-    PointerCoords pointerCoords[2];
-    pointerCoords[0].clear();
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 11);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 12);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 13);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 14);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 15);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 16);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 17);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 18);
-    pointerCoords[1].clear();
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 20);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 21);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 23);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 24);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 25);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
+    mSamples[0].pointerCoords[0].clear();
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 11);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 12);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 13);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 14);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 15);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 16);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 17);
+    mSamples[0].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 18);
+    mSamples[0].pointerCoords[1].clear();
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 20);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 21);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 23);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 24);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 25);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
+    mSamples[0].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
+
+    mSamples[1].pointerCoords[0].clear();
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 112);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 113);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 114);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 115);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 116);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 117);
+    mSamples[1].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 118);
+    mSamples[1].pointerCoords[1].clear();
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 120);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 121);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 122);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 123);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 124);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 125);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127);
+    mSamples[1].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128);
+
+    mSamples[2].pointerCoords[0].clear();
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 212);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 213);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 214);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 215);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 216);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 217);
+    mSamples[2].pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 218);
+    mSamples[2].pointerCoords[1].clear();
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 220);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 221);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 222);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 223);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 224);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 225);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227);
+    mSamples[2].pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228);
+}
+
+void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
     event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC,
                       AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
                       AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
                       MotionClassification::NONE, mTransform, 2.0f, 2.1f,
                       AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
                       mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2,
-                      pointerProperties, pointerCoords);
-
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 112);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 113);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 114);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 115);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 116);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 117);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 118);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 120);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 121);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 122);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 123);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 124);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 125);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128);
-    event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords);
-
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 212);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 213);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 214);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 215);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 216);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 217);
-    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 218);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 220);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 221);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 222);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 223);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 224);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 225);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227);
-    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228);
-    event->addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords);
+                      mPointerProperties, mSamples[0].pointerCoords);
+    event->addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords);
+    event->addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords);
 }
 
 void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
@@ -356,51 +370,65 @@
     ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1));
     ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime());
 
-    ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
-    ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
-    ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
-    ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
-    ASSERT_EQ(211, event->getRawPointerCoords(0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
-    ASSERT_EQ(221, event->getRawPointerCoords(1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+    // Ensure the underlying PointerCoords are identical.
+    for (int sampleIdx = 0; sampleIdx < 3; sampleIdx++) {
+        for (int pointerIdx = 0; pointerIdx < 2; pointerIdx++) {
+            ASSERT_EQ(mSamples[sampleIdx].pointerCoords[pointerIdx],
+                      event->getSamplePointerCoords()[sampleIdx * 2 + pointerIdx]);
+        }
+    }
 
-    ASSERT_EQ(RAW_Y_OFFSET + 11 * RAW_Y_SCALE,
-              event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
-    ASSERT_EQ(RAW_Y_OFFSET + 21 * RAW_Y_SCALE,
-              event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
-    ASSERT_EQ(RAW_Y_OFFSET + 111 * RAW_Y_SCALE,
-              event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
-    ASSERT_EQ(RAW_Y_OFFSET + 121 * RAW_Y_SCALE,
-              event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
-    ASSERT_EQ(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
-    ASSERT_EQ(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
+    ASSERT_NEAR(11, event->getHistoricalRawPointerCoords(0, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y),
+                EPSILON);
+    ASSERT_NEAR(21, event->getHistoricalRawPointerCoords(1, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y),
+                EPSILON);
+    ASSERT_NEAR(111, event->getHistoricalRawPointerCoords(0, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y),
+                EPSILON);
+    ASSERT_NEAR(121, event->getHistoricalRawPointerCoords(1, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y),
+                EPSILON);
+    ASSERT_NEAR(211, event->getRawPointerCoords(0)->getAxisValue(AMOTION_EVENT_AXIS_Y), EPSILON);
+    ASSERT_NEAR(221, event->getRawPointerCoords(1)->getAxisValue(AMOTION_EVENT_AXIS_Y), EPSILON);
 
-    ASSERT_EQ(RAW_X_OFFSET + 10 * RAW_X_SCALE, event->getHistoricalRawX(0, 0));
-    ASSERT_EQ(RAW_X_OFFSET + 20 * RAW_X_SCALE, event->getHistoricalRawX(1, 0));
-    ASSERT_EQ(RAW_X_OFFSET + 110 * RAW_X_SCALE, event->getHistoricalRawX(0, 1));
-    ASSERT_EQ(RAW_X_OFFSET + 120 * RAW_X_SCALE, event->getHistoricalRawX(1, 1));
-    ASSERT_EQ(RAW_X_OFFSET + 210 * RAW_X_SCALE, event->getRawX(0));
-    ASSERT_EQ(RAW_X_OFFSET + 220 * RAW_X_SCALE, event->getRawX(1));
+    ASSERT_NEAR(RAW_Y_OFFSET + 11 * RAW_Y_SCALE,
+                event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 21 * RAW_Y_SCALE,
+                event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 111 * RAW_Y_SCALE,
+                event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 121 * RAW_Y_SCALE,
+                event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0),
+                EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1),
+                EPSILON);
 
-    ASSERT_EQ(RAW_Y_OFFSET + 11 * RAW_Y_SCALE, event->getHistoricalRawY(0, 0));
-    ASSERT_EQ(RAW_Y_OFFSET + 21 * RAW_Y_SCALE, event->getHistoricalRawY(1, 0));
-    ASSERT_EQ(RAW_Y_OFFSET + 111 * RAW_Y_SCALE, event->getHistoricalRawY(0, 1));
-    ASSERT_EQ(RAW_Y_OFFSET + 121 * RAW_Y_SCALE, event->getHistoricalRawY(1, 1));
-    ASSERT_EQ(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawY(0));
-    ASSERT_EQ(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawY(1));
+    ASSERT_NEAR(RAW_X_OFFSET + 10 * RAW_X_SCALE, event->getHistoricalRawX(0, 0), EPSILON);
+    ASSERT_NEAR(RAW_X_OFFSET + 20 * RAW_X_SCALE, event->getHistoricalRawX(1, 0), EPSILON);
+    ASSERT_NEAR(RAW_X_OFFSET + 110 * RAW_X_SCALE, event->getHistoricalRawX(0, 1), EPSILON);
+    ASSERT_NEAR(RAW_X_OFFSET + 120 * RAW_X_SCALE, event->getHistoricalRawX(1, 1), EPSILON);
+    ASSERT_NEAR(RAW_X_OFFSET + 210 * RAW_X_SCALE, event->getRawX(0), EPSILON);
+    ASSERT_NEAR(RAW_X_OFFSET + 220 * RAW_X_SCALE, event->getRawX(1), EPSILON);
 
-    ASSERT_EQ(X_OFFSET + 10 * X_SCALE, event->getHistoricalX(0, 0));
-    ASSERT_EQ(X_OFFSET + 20 * X_SCALE, event->getHistoricalX(1, 0));
-    ASSERT_EQ(X_OFFSET + 110 * X_SCALE, event->getHistoricalX(0, 1));
-    ASSERT_EQ(X_OFFSET + 120 * X_SCALE, event->getHistoricalX(1, 1));
-    ASSERT_EQ(X_OFFSET + 210 * X_SCALE, event->getX(0));
-    ASSERT_EQ(X_OFFSET + 220 * X_SCALE, event->getX(1));
+    ASSERT_NEAR(RAW_Y_OFFSET + 11 * RAW_Y_SCALE, event->getHistoricalRawY(0, 0), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 21 * RAW_Y_SCALE, event->getHistoricalRawY(1, 0), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 111 * RAW_Y_SCALE, event->getHistoricalRawY(0, 1), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 121 * RAW_Y_SCALE, event->getHistoricalRawY(1, 1), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawY(0), EPSILON);
+    ASSERT_NEAR(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawY(1), EPSILON);
 
-    ASSERT_EQ(Y_OFFSET + 11 * Y_SCALE, event->getHistoricalY(0, 0));
-    ASSERT_EQ(Y_OFFSET + 21 * Y_SCALE, event->getHistoricalY(1, 0));
-    ASSERT_EQ(Y_OFFSET + 111 * Y_SCALE, event->getHistoricalY(0, 1));
-    ASSERT_EQ(Y_OFFSET + 121 * Y_SCALE, event->getHistoricalY(1, 1));
-    ASSERT_EQ(Y_OFFSET + 211 * Y_SCALE, event->getY(0));
-    ASSERT_EQ(Y_OFFSET + 221 * Y_SCALE, event->getY(1));
+    ASSERT_NEAR(X_OFFSET + 10 * X_SCALE, event->getHistoricalX(0, 0), EPSILON);
+    ASSERT_NEAR(X_OFFSET + 20 * X_SCALE, event->getHistoricalX(1, 0), EPSILON);
+    ASSERT_NEAR(X_OFFSET + 110 * X_SCALE, event->getHistoricalX(0, 1), EPSILON);
+    ASSERT_NEAR(X_OFFSET + 120 * X_SCALE, event->getHistoricalX(1, 1), EPSILON);
+    ASSERT_NEAR(X_OFFSET + 210 * X_SCALE, event->getX(0), EPSILON);
+    ASSERT_NEAR(X_OFFSET + 220 * X_SCALE, event->getX(1), EPSILON);
+
+    ASSERT_NEAR(Y_OFFSET + 11 * Y_SCALE, event->getHistoricalY(0, 0), EPSILON);
+    ASSERT_NEAR(Y_OFFSET + 21 * Y_SCALE, event->getHistoricalY(1, 0), EPSILON);
+    ASSERT_NEAR(Y_OFFSET + 111 * Y_SCALE, event->getHistoricalY(0, 1), EPSILON);
+    ASSERT_NEAR(Y_OFFSET + 121 * Y_SCALE, event->getHistoricalY(1, 1), EPSILON);
+    ASSERT_NEAR(Y_OFFSET + 211 * Y_SCALE, event->getY(0), EPSILON);
+    ASSERT_NEAR(Y_OFFSET + 221 * Y_SCALE, event->getY(1), EPSILON);
 
     ASSERT_EQ(12, event->getHistoricalPressure(0, 0));
     ASSERT_EQ(22, event->getHistoricalPressure(1, 0));
@@ -532,10 +560,10 @@
     ASSERT_EQ(X_OFFSET * 2, event.getXOffset());
     ASSERT_EQ(Y_OFFSET * 2, event.getYOffset());
 
-    ASSERT_EQ((RAW_X_OFFSET + 210 * RAW_X_SCALE) * 2, event.getRawX(0));
-    ASSERT_EQ((RAW_Y_OFFSET + 211 * RAW_Y_SCALE) * 2, event.getRawY(0));
-    ASSERT_EQ((X_OFFSET + 210 * X_SCALE) * 2, event.getX(0));
-    ASSERT_EQ((Y_OFFSET + 211 * Y_SCALE) * 2, event.getY(0));
+    ASSERT_NEAR((RAW_X_OFFSET + 210 * RAW_X_SCALE) * 2, event.getRawX(0), EPSILON);
+    ASSERT_NEAR((RAW_Y_OFFSET + 211 * RAW_Y_SCALE) * 2, event.getRawY(0), EPSILON);
+    ASSERT_NEAR((X_OFFSET + 210 * X_SCALE) * 2, event.getX(0), EPSILON);
+    ASSERT_NEAR((Y_OFFSET + 211 * Y_SCALE) * 2, event.getY(0), EPSILON);
     ASSERT_EQ(212, event.getPressure(0));
     ASSERT_EQ(213, event.getSize(0));
     ASSERT_EQ(214 * 2, event.getTouchMajor(0));
@@ -773,18 +801,18 @@
 
     // The x and y axes should have the window transform applied.
     const auto newPoint = transform.transform(60, 100);
-    ASSERT_EQ(newPoint.x, event.getX(0));
-    ASSERT_EQ(newPoint.y, event.getY(0));
+    ASSERT_NEAR(newPoint.x, event.getX(0), EPSILON);
+    ASSERT_NEAR(newPoint.y, event.getY(0), EPSILON);
 
     // The raw values should have the display transform applied.
     const auto raw = rawTransform.transform(60, 100);
-    ASSERT_EQ(raw.x, event.getRawX(0));
-    ASSERT_EQ(raw.y, event.getRawY(0));
+    ASSERT_NEAR(raw.x, event.getRawX(0), EPSILON);
+    ASSERT_NEAR(raw.y, event.getRawY(0), EPSILON);
 
     // Relative values should have the window transform applied without any translation.
     const auto rel = transformWithoutTranslation(transform, 42, 96);
-    ASSERT_EQ(rel.x, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
-    ASSERT_EQ(rel.y, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
+    ASSERT_NEAR(rel.x, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0), EPSILON);
+    ASSERT_NEAR(rel.y, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0), EPSILON);
 }
 
 TEST_F(MotionEventTest, Initialize_SetsClassification) {
@@ -851,4 +879,42 @@
     ASSERT_EQ(4, event.getYCursorPosition());
 }
 
+TEST_F(MotionEventTest, CoordinatesAreRoundedAppropriately) {
+    // These are specifically integral values, since we are testing for rounding.
+    const vec2 EXPECTED{400.f, 700.f};
+
+    // Pick a transform such that transforming the point with its inverse and bringing that
+    // back to the original coordinate space results in a non-zero error amount due to the
+    // nature of floating point arithmetics. This can happen when the display is scaled.
+    // For example, the 'adb shell wm size' command can be used to set an override for the
+    // logical display size, which could result in the display being scaled.
+    constexpr float scale = 720.f / 1080.f;
+    ui::Transform transform;
+    transform.set(scale, 0, 0, scale);
+    ASSERT_NE(EXPECTED, transform.transform(transform.inverse().transform(EXPECTED)));
+
+    // Store the inverse-transformed values in the motion event.
+    const vec2 rawCoords = transform.inverse().transform(EXPECTED);
+    PointerCoords pc{};
+    pc.setAxisValue(AMOTION_EVENT_AXIS_X, rawCoords.x);
+    pc.setAxisValue(AMOTION_EVENT_AXIS_Y, rawCoords.y);
+    PointerProperties pp{};
+    MotionEvent event;
+    event.initialize(InputEvent::nextId(), 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC,
+                     AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
+                     AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
+                     MotionClassification::NONE, transform, 2.0f, 2.1f, rawCoords.x, rawCoords.y,
+                     transform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 1, &pp, &pc);
+
+    // When using the getters from the MotionEvent to obtain the coordinates, the transformed
+    // values should be rounded by an appropriate amount so that they now precisely equal the
+    // original coordinates.
+    ASSERT_EQ(EXPECTED.x, event.getX(0));
+    ASSERT_EQ(EXPECTED.y, event.getY(0));
+    ASSERT_EQ(EXPECTED.x, event.getRawX(0));
+    ASSERT_EQ(EXPECTED.y, event.getRawY(0));
+    ASSERT_EQ(EXPECTED.x, event.getXCursorPosition());
+    ASSERT_EQ(EXPECTED.y, event.getYCursorPosition());
+}
+
 } // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 05bc0bc..8393e99 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -32,6 +32,8 @@
 
 namespace android {
 
+constexpr static float EPSILON = MotionEvent::ROUNDING_PRECISION;
+
 class InputPublisherAndConsumerTest : public testing::Test {
 protected:
     std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
@@ -233,10 +235,10 @@
     EXPECT_EQ(yOffset, motionEvent->getYOffset());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
-    EXPECT_EQ(xCursorPosition, motionEvent->getRawXCursorPosition());
-    EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());
-    EXPECT_EQ(xCursorPosition * xScale + xOffset, motionEvent->getXCursorPosition());
-    EXPECT_EQ(yCursorPosition * yScale + yOffset, motionEvent->getYCursorPosition());
+    EXPECT_NEAR(xCursorPosition, motionEvent->getRawXCursorPosition(), EPSILON);
+    EXPECT_NEAR(yCursorPosition, motionEvent->getRawYCursorPosition(), EPSILON);
+    EXPECT_NEAR(xCursorPosition * xScale + xOffset, motionEvent->getXCursorPosition(), EPSILON);
+    EXPECT_NEAR(yCursorPosition * yScale + yOffset, motionEvent->getYCursorPosition(), EPSILON);
     EXPECT_EQ(rawTransform, motionEvent->getRawTransform());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
     EXPECT_EQ(eventTime, motionEvent->getEventTime());
@@ -249,10 +251,12 @@
         EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i));
 
         const auto& pc = pointerCoords[i];
-        EXPECT_EQ(pc.getX() * rawXScale + rawXOffset, motionEvent->getRawX(i));
-        EXPECT_EQ(pc.getY() * rawYScale + rawYOffset, motionEvent->getRawY(i));
-        EXPECT_EQ(pc.getX() * xScale + xOffset, motionEvent->getX(i));
-        EXPECT_EQ(pc.getY() * yScale + yOffset, motionEvent->getY(i));
+        EXPECT_EQ(pc, motionEvent->getSamplePointerCoords()[i]);
+
+        EXPECT_NEAR(pc.getX() * rawXScale + rawXOffset, motionEvent->getRawX(i), EPSILON);
+        EXPECT_NEAR(pc.getY() * rawYScale + rawYOffset, motionEvent->getRawY(i), EPSILON);
+        EXPECT_NEAR(pc.getX() * xScale + xOffset, motionEvent->getX(i), EPSILON);
+        EXPECT_NEAR(pc.getY() * yScale + yOffset, motionEvent->getY(i), EPSILON);
         EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), motionEvent->getPressure(i));
         EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_SIZE), motionEvent->getSize(i));
         EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), motionEvent->getTouchMajor(i));
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 3762e66..73a05fc 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -24,14 +24,49 @@
 
 #include <private/android/AHardwareBufferHelpers.h>
 
+#include <android/binder_libbinder.h>
+#include <dlfcn.h>
 #include <log/log.h>
 #include <ui/GraphicBuffer.h>
-#include <gui/Surface.h>
-#include <gui/view/Surface.h>
-#include <android/binder_libbinder.h>
 
 using namespace android;
 
+#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
+#error libnativewindow can only be built for system
+#endif
+
+using android_view_Surface_writeToParcel = status_t (*)(ANativeWindow* _Nonnull window,
+                                                        Parcel* _Nonnull parcel);
+
+using android_view_Surface_readFromParcel =
+        status_t (*)(const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow);
+
+struct SurfaceParcelables {
+    android_view_Surface_writeToParcel write = nullptr;
+    android_view_Surface_readFromParcel read = nullptr;
+};
+
+const SurfaceParcelables* getSurfaceParcelFunctions() {
+    static SurfaceParcelables funcs = []() -> SurfaceParcelables {
+        SurfaceParcelables ret;
+        void* dl = dlopen("libgui.so", RTLD_NOW);
+        LOG_ALWAYS_FATAL_IF(!dl, "Failed to find libgui.so");
+        ret.write =
+                (android_view_Surface_writeToParcel)dlsym(dl, "android_view_Surface_writeToParcel");
+        LOG_ALWAYS_FATAL_IF(!ret.write,
+                            "libgui.so missing android_view_Surface_writeToParcel; "
+                            "loaded wrong libgui?");
+        ret.read =
+                (android_view_Surface_readFromParcel)dlsym(dl,
+                                                           "android_view_Surface_readFromParcel");
+        LOG_ALWAYS_FATAL_IF(!ret.read,
+                            "libgui.so missing android_view_Surface_readFromParcel; "
+                            "loaded wrong libgui?");
+        return ret;
+    }();
+    return &funcs;
+}
+
 static int32_t query(ANativeWindow* window, int what) {
     int value;
     int res = window->query(window, what, &value);
@@ -64,13 +99,6 @@
             return false;
     }
 }
-static sp<IGraphicBufferProducer> IGraphicBufferProducer_from_ANativeWindow(ANativeWindow* window) {
-    return Surface::getIGraphicBufferProducer(window);
-}
-
-static sp<IBinder> SurfaceControlHandle_from_ANativeWindow(ANativeWindow* window) {
-    return Surface::getSurfaceControlHandle(window);
-}
 
 /**************************************************************************************************
  * NDK
@@ -348,38 +376,24 @@
 
 binder_status_t ANativeWindow_readFromParcel(
         const AParcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) {
-    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
-
-    // Use a android::view::Surface to unparcel the window
-    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
-    status_t ret = shimSurface->readFromParcel(nativeParcel);
-    if (ret != OK) {
-        ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__);
-        return STATUS_BAD_VALUE;
+    auto funcs = getSurfaceParcelFunctions();
+    if (funcs->read == nullptr) {
+        ALOGE("Failed to load Surface_readFromParcel implementation");
+        return STATUS_FAILED_TRANSACTION;
     }
-    sp<Surface> surface = sp<Surface>::make(
-            shimSurface->graphicBufferProducer, false, shimSurface->surfaceControlHandle);
-    ANativeWindow* anw = surface.get();
-    ANativeWindow_acquire(anw);
-    *outWindow = anw;
-    return STATUS_OK;
+    const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
+    return funcs->read(nativeParcel, outWindow);
 }
 
 binder_status_t ANativeWindow_writeToParcel(
         ANativeWindow* _Nonnull window, AParcel* _Nonnull parcel) {
-    int value;
-    int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value);
-    if (err != OK || value != NATIVE_WINDOW_SURFACE) {
-        ALOGE("Error: ANativeWindow is not backed by Surface");
-        return STATUS_BAD_VALUE;
+    auto funcs = getSurfaceParcelFunctions();
+    if (funcs->write == nullptr) {
+        ALOGE("Failed to load Surface_writeToParcel implementation");
+        return STATUS_FAILED_TRANSACTION;
     }
-    // Use a android::view::Surface to parcelize the window
-    std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>();
-    shimSurface->graphicBufferProducer = IGraphicBufferProducer_from_ANativeWindow(window);
-    shimSurface->surfaceControlHandle = SurfaceControlHandle_from_ANativeWindow(window);
-
     Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel);
-    return shimSurface->writeToParcel(nativeParcel);
+    return funcs->write(window, nativeParcel);
 }
 
 /**************************************************************************************************
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index f6ab7b2..53372c9 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -22,6 +22,8 @@
 #include <aidlcommonsupport/NativeHandle.h>
 #include <android/binder_enums.h>
 #include <android/binder_manager.h>
+#include <cutils/android_filesystem_config.h>
+#include <cutils/multiuser.h>
 #include <gralloctypes/Gralloc4.h>
 #include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
@@ -1195,8 +1197,15 @@
     mAllocator = IAllocator::getService();
     if (__builtin_available(android 31, *)) {
         if (hasIAllocatorAidl()) {
-            mAidlAllocator = AidlIAllocator::fromBinder(ndk::SpAIBinder(
-                    AServiceManager_waitForService(kAidlAllocatorServiceName.c_str())));
+            // TODO(b/269517338): Perform the isolated checking for this in service manager instead.
+            uid_t aid = multiuser_get_app_id(getuid());
+            if (aid >= AID_ISOLATED_START && aid <= AID_ISOLATED_END) {
+                mAidlAllocator = AidlIAllocator::fromBinder(ndk::SpAIBinder(
+                        AServiceManager_getService(kAidlAllocatorServiceName.c_str())));
+            } else {
+                mAidlAllocator = AidlIAllocator::fromBinder(ndk::SpAIBinder(
+                        AServiceManager_waitForService(kAidlAllocatorServiceName.c_str())));
+            }
             ALOGE_IF(!mAidlAllocator, "AIDL IAllocator declared but failed to get service");
         }
     }
diff --git a/opengl/OWNERS b/opengl/OWNERS
index 379f763..3d60a1d 100644
--- a/opengl/OWNERS
+++ b/opengl/OWNERS
@@ -1,11 +1,6 @@
-abdolrashidi@google.com
-cclao@google.com
 chrisforbes@google.com
 cnorthrop@google.com
 ianelliott@google.com
 jessehall@google.com
-lfy@google.com
 lpy@google.com
-romanl@google.com
 vantablack@google.com
-yuxinhu@google.com
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 86c788d..aecfc6b 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -231,7 +231,7 @@
 
 int BlobCache::unflatten(void const* buffer, size_t size) {
     // All errors should result in the BlobCache being in an empty state.
-    mCacheEntries.clear();
+    clear();
 
     // Read the cache header
     if (size < sizeof(Header)) {
@@ -258,7 +258,7 @@
     size_t numEntries = header->mNumEntries;
     for (size_t i = 0; i < numEntries; i++) {
         if (byteOffset + sizeof(EntryHeader) > size) {
-            mCacheEntries.clear();
+            clear();
             ALOGE("unflatten: not enough room for cache entry headers");
             return -EINVAL;
         }
@@ -270,7 +270,7 @@
 
         size_t totalSize = align4(entrySize);
         if (byteOffset + totalSize > size) {
-            mCacheEntries.clear();
+            clear();
             ALOGE("unflatten: not enough room for cache entry headers");
             return -EINVAL;
         }
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index ff03d30..52078ff 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -117,7 +117,10 @@
 
     // clear flushes out all contents of the cache then the BlobCache, leaving
     // it in an empty state.
-    void clear() { mCacheEntries.clear(); }
+    void clear() {
+        mCacheEntries.clear();
+        mTotalSize = 0;
+    }
 
 protected:
     // mMaxTotalSize is the maximum size that all cache entries can occupy. This
diff --git a/opengl/libs/EGL/BlobCache_test.cpp b/opengl/libs/EGL/BlobCache_test.cpp
index ceea0fb..450c128 100644
--- a/opengl/libs/EGL/BlobCache_test.cpp
+++ b/opengl/libs/EGL/BlobCache_test.cpp
@@ -466,4 +466,31 @@
     ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
 }
 
+// Test for a divide by zero bug (b/239862516). Before the fix, unflatten() would not reset
+// mTotalSize when it encountered an error, which would trigger division by 0 in clean() in the
+// right conditions.
+TEST_F(BlobCacheFlattenTest, SetAfterFailedUnflatten) {
+    // isCleanable() must be true, so mTotalSize must be > mMaxTotalSize / 2 after unflattening
+    // after one entry is lost. To make this the case, MaxTotalSize is 30 and three 10 sized
+    // entries are used. One of those entries is lost, resulting in mTotalSize=20
+    const size_t kMaxKeySize = 10;
+    const size_t kMaxValueSize = 10;
+    const size_t kMaxTotalSize = 30;
+    mBC.reset(new BlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize));
+    mBC2.reset(new BlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize));
+    mBC->set("aaaaa", 5, "aaaaa", 5);
+    mBC->set("bbbbb", 5, "bbbbb", 5);
+    mBC->set("ccccc", 5, "ccccc", 5);
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+
+    ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size - 10));
+    delete[] flat;
+
+    // This line will trigger clean() which caused a crash.
+    mBC2->set("dddddddddd", 10, "dddddddddd", 10);
+}
+
 } // namespace android
diff --git a/services/batteryservice/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h
index a2e4115..bf6189d 100644
--- a/services/batteryservice/include/batteryservice/BatteryService.h
+++ b/services/batteryservice/include/batteryservice/BatteryService.h
@@ -37,6 +37,7 @@
     BATTERY_PROP_CHARGING_POLICY = 7, // equals BATTERY_PROPERTY_CHARGING_POLICY
     BATTERY_PROP_MANUFACTURING_DATE = 8, // equals BATTERY_PROPERTY_MANUFACTURING_DATE
     BATTERY_PROP_FIRST_USAGE_DATE = 9, // equals BATTERY_PROPERTY_FIRST_USAGE_DATE
+    BATTERY_PROP_STATE_OF_HEALTH = 10, // equals BATTERY_PROPERTY_STATE_OF_HEALTH
 };
 
 struct BatteryProperties {
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 86f6c7f..51642f9 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -24,9 +24,6 @@
 cc_test {
     name: "gpuservice_unittest",
     test_suites: ["device-tests"],
-    sanitize: {
-        address: true,
-    },
     srcs: [
         "GpuMemTest.cpp",
         "GpuMemTracerTest.cpp",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index eb97a68..96164c0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -107,6 +107,8 @@
 constexpr int LOGTAG_INPUT_FOCUS = 62001;
 constexpr int LOGTAG_INPUT_CANCEL = 62003;
 
+const ui::Transform kIdentityTransform;
+
 inline nsecs_t now() {
     return systemTime(SYSTEM_TIME_MONOTONIC);
 }
@@ -459,8 +461,8 @@
 }
 
 // Returns true if the given window can accept pointer events at the given display location.
-bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, int32_t x, int32_t y,
-                          bool isStylus) {
+bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, float x, float y,
+                          bool isStylus, const ui::Transform& displayTransform) {
     const auto inputConfig = windowInfo.inputConfig;
     if (windowInfo.displayId != displayId ||
         inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
@@ -470,7 +472,17 @@
     if (inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) && !windowCanInterceptTouch) {
         return false;
     }
-    if (!windowInfo.touchableRegionContainsPoint(x, y)) {
+
+    // Window Manager works in the logical display coordinate space. When it specifies bounds for a
+    // window as (l, t, r, b), the range of x in [l, r) and y in [t, b) are considered to be inside
+    // the window. Points on the right and bottom edges should not be inside the window, so we need
+    // to be careful about performing a hit test when the display is rotated, since the "right" and
+    // "bottom" of the window will be different in the display (un-rotated) space compared to in the
+    // logical display in which WM determined the bounds. Perform the hit test in the logical
+    // display space to ensure these edges are considered correctly in all orientations.
+    const auto touchableRegion = displayTransform.transform(windowInfo.touchableRegion);
+    const auto p = displayTransform.transform(x, y);
+    if (!touchableRegion.contains(std::floor(p.x), std::floor(p.y))) {
         return false;
     }
     return true;
@@ -928,10 +940,8 @@
     // the touch into the other window.
     if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
         int32_t displayId = motionEntry.displayId;
-        int32_t x = static_cast<int32_t>(
-                motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
-        int32_t y = static_cast<int32_t>(
-                motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
+        const float x = motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
+        const float y = motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
 
         const bool isStylus = isPointerFromStylus(motionEntry, 0 /*pointerIndex*/);
         sp<WindowInfoHandle> touchedWindowHandle =
@@ -1058,8 +1068,8 @@
     }
 }
 
-sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
-                                                                int32_t y, TouchState* touchState,
+sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, float x, float y,
+                                                                TouchState* touchState,
                                                                 bool isStylus,
                                                                 bool addOutsideTargets,
                                                                 bool ignoreDragWindow) {
@@ -1074,7 +1084,8 @@
         }
 
         const WindowInfo& info = *windowHandle->getInfo();
-        if (!info.isSpy() && windowAcceptsTouchAt(info, displayId, x, y, isStylus)) {
+        if (!info.isSpy() &&
+            windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
             return windowHandle;
         }
 
@@ -1088,14 +1099,14 @@
 }
 
 std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
-        int32_t displayId, int32_t x, int32_t y, bool isStylus) const {
+        int32_t displayId, float x, float y, bool isStylus) const {
     // Traverse windows from front to back and gather the touched spy windows.
     std::vector<sp<WindowInfoHandle>> spyWindows;
     const auto& windowHandles = getWindowHandlesLocked(displayId);
     for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
         const WindowInfo& info = *windowHandle->getInfo();
 
-        if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus)) {
+        if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
             continue;
         }
         if (!info.isSpy()) {
@@ -2057,16 +2068,16 @@
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
 
-        int32_t x;
-        int32_t y;
+        float x;
+        float y;
         const int32_t pointerIndex = getMotionEventActionPointerIndex(action);
         // Always dispatch mouse events to cursor position.
         if (isFromMouse) {
-            x = int32_t(entry.xCursorPosition);
-            y = int32_t(entry.yCursorPosition);
+            x = entry.xCursorPosition;
+            y = entry.yCursorPosition;
         } else {
-            x = int32_t(entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
-            y = int32_t(entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
+            x = entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X);
+            y = entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y);
         }
         const bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
         const bool isStylus = isPointerFromStylus(entry, pointerIndex);
@@ -2075,8 +2086,7 @@
 
         // Handle the case where we did not find a window.
         if (newTouchedWindowHandle == nullptr) {
-            ALOGD("No new touched window at (%" PRId32 ", %" PRId32 ") in display %" PRId32, x, y,
-                  displayId);
+            ALOGD("No new touched window at (%.1f, %.1f) in display %" PRId32, x, y, displayId);
             // Try to assign the pointer to the first foreground window we find, if there is one.
             newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();
         }
@@ -2123,7 +2133,8 @@
         }
 
         if (newTouchedWindows.empty()) {
-            ALOGI("Dropping event because there is no touchable window at (%d, %d) on display %d.",
+            ALOGI("Dropping event because there is no touchable window at (%.1f, %.1f) on display "
+                  "%d.",
                   x, y, displayId);
             injectionResult = InputEventInjectionResult::FAILED;
             goto Failed;
@@ -2157,7 +2168,8 @@
                         computeTouchOcclusionInfoLocked(windowHandle, x, y);
                 if (!isTouchTrustedLocked(occlusionInfo)) {
                     if (DEBUG_TOUCH_OCCLUSION) {
-                        ALOGD("Stack of obscuring windows during untrusted touch (%d, %d):", x, y);
+                        ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x,
+                              y);
                         for (const auto& log : occlusionInfo.debugInfo) {
                             ALOGD("%s", log.c_str());
                         }
@@ -2218,8 +2230,8 @@
         // Check whether touches should slip outside of the current foreground window.
         if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 &&
             tempTouchState.isSlippery()) {
-            const int32_t x = int32_t(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
-            const int32_t y = int32_t(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
+            const float x = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
+            const float y = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
 
             const bool isStylus = isPointerFromStylus(entry, 0 /*pointerIndex*/);
             sp<WindowInfoHandle> oldTouchedWindowHandle =
@@ -2541,8 +2553,8 @@
     }
 
     const int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK;
-    const int32_t x = entry.pointerCoords[pointerIndex].getX();
-    const int32_t y = entry.pointerCoords[pointerIndex].getY();
+    const float x = entry.pointerCoords[pointerIndex].getX();
+    const float y = entry.pointerCoords[pointerIndex].getY();
 
     switch (maskedAction) {
         case AMOTION_EVENT_ACTION_MOVE: {
@@ -4582,6 +4594,12 @@
     return getWindowHandleLocked(focusedToken, displayId);
 }
 
+ui::Transform InputDispatcher::getTransformLocked(int32_t displayId) const {
+    auto displayInfoIt = mDisplayInfos.find(displayId);
+    return displayInfoIt != mDisplayInfos.end() ? displayInfoIt->second.transform
+                                                : kIdentityTransform;
+}
+
 bool InputDispatcher::hasResponsiveConnectionLocked(WindowInfoHandle& windowHandle) const {
     sp<Connection> connection = getConnectionLocked(windowHandle.getToken());
     const bool noInputChannel =
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index ed89ed0..24e7432 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -240,11 +240,11 @@
     std::shared_ptr<EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
 
     sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
-            int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool isStylus = false,
+            int32_t displayId, float x, float y, TouchState* touchState, bool isStylus = false,
             bool addOutsideTargets = false, bool ignoreDragWindow = false) REQUIRES(mLock);
 
     std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
-            int32_t displayId, int32_t x, int32_t y, bool isStylus) const REQUIRES(mLock);
+            int32_t displayId, float x, float y, bool isStylus) const REQUIRES(mLock);
 
     sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(int32_t displayId) const
             REQUIRES(mLock);
@@ -370,6 +370,7 @@
             int32_t displayId) const REQUIRES(mLock);
     sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
             const sp<IBinder>& windowHandleToken) const REQUIRES(mLock);
+    ui::Transform getTransformLocked(int32_t displayId) const REQUIRES(mLock);
 
     // Same function as above, but faster. Since displayId is provided, this avoids the need
     // to loop through all displays.
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index fce0f99..e860e3c 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -128,10 +128,10 @@
             const auto& motionEvent = static_cast<const MotionEvent&>(event);
             EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
             EXPECT_EQ(motionEvent.getAction(), args.action);
-            EXPECT_EQ(motionEvent.getX(0), point.x);
-            EXPECT_EQ(motionEvent.getY(0), point.y);
-            EXPECT_EQ(motionEvent.getRawX(0), point.x);
-            EXPECT_EQ(motionEvent.getRawY(0), point.y);
+            EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
+            EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
+            EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
+            EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
         });
     }
 
@@ -2481,8 +2481,7 @@
 public:
     void SetUp() override {
         InputDispatcherTest::SetUp();
-        mDisplayInfos.clear();
-        mWindowInfos.clear();
+        removeAllWindowsAndDisplays();
     }
 
     void addDisplayInfo(int displayId, const ui::Transform& transform) {
@@ -2498,6 +2497,11 @@
         mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
     }
 
+    void removeAllWindowsAndDisplays() {
+        mDisplayInfos.clear();
+        mWindowInfos.clear();
+    }
+
     // Set up a test scenario where the display has a scaled projection and there are two windows
     // on the display.
     std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
@@ -2529,11 +2533,11 @@
     std::vector<gui::WindowInfo> mWindowInfos;
 };
 
-TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
+TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
     auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
     // Send down to the first window. The point is represented in the display space. The point is
-    // selected so that if the hit test was done with the transform applied to it, then it would
-    // end up in the incorrect window.
+    // selected so that if the hit test was performed with the point and the bounds being in
+    // different coordinate spaces, the event would end up in the incorrect window.
     NotifyMotionArgs downMotionArgs =
             generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                                ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
@@ -2608,6 +2612,78 @@
     EXPECT_EQ(80, event->getY(0));
 }
 
+/** Ensure consistent behavior of InputDispatcher in all orientations. */
+class InputDispatcherDisplayOrientationFixture
+      : public InputDispatcherDisplayProjectionTest,
+        public ::testing::WithParamInterface<ui::Rotation> {};
+
+// This test verifies the touchable region of a window for all rotations of the display by tapping
+// in different locations on the display, specifically points close to the four corners of a
+// window.
+TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
+    constexpr static int32_t displayWidth = 400;
+    constexpr static int32_t displayHeight = 800;
+
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+    const auto rotation = GetParam();
+
+    // Set up the display with the specified rotation.
+    const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
+    const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
+    const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
+    const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
+                                         logicalDisplayWidth, logicalDisplayHeight);
+    addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
+
+    // Create a window with its bounds determined in the logical display.
+    const Rect frameInLogicalDisplay(100, 100, 200, 300);
+    const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
+    sp<FakeWindowHandle> window =
+            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+    window->setFrame(frameInDisplay, displayTransform);
+    addWindow(window);
+
+    // The following points in logical display space should be inside the window.
+    static const std::array<vec2, 4> insidePoints{
+            {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
+    for (const auto pointInsideWindow : insidePoints) {
+        const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
+        const PointF pointInDisplaySpace{p.x, p.y};
+        const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                             ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
+        mDispatcher->notifyMotion(&down);
+        window->consumeMotionDown();
+
+        const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                           ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
+        mDispatcher->notifyMotion(&up);
+        window->consumeMotionUp();
+    }
+
+    // The following points in logical display space should be outside the window.
+    static const std::array<vec2, 5> outsidePoints{
+            {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
+    for (const auto pointOutsideWindow : outsidePoints) {
+        const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
+        const PointF pointInDisplaySpace{p.x, p.y};
+        const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+                                             ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
+        mDispatcher->notifyMotion(&down);
+
+        const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+                                           ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
+        mDispatcher->notifyMotion(&up);
+    }
+    window->assertNoEvents();
+}
+
+// Run the precision tests for all rotations.
+INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
+                         InputDispatcherDisplayOrientationFixture,
+                         ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
+                                           ui::ROTATION_270));
+
 using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
                                             sp<IBinder>, sp<IBinder>)>;
 
diff --git a/services/memtrackproxy/MemtrackProxy.cpp b/services/memtrackproxy/MemtrackProxy.cpp
index 4676167..9e41a93 100644
--- a/services/memtrackproxy/MemtrackProxy.cpp
+++ b/services/memtrackproxy/MemtrackProxy.cpp
@@ -97,9 +97,14 @@
     return calling_pid == request_pid;
 }
 
-MemtrackProxy::MemtrackProxy()
-      : memtrack_hidl_instance_(MemtrackProxy::MemtrackHidlInstance()),
-        memtrack_aidl_instance_(MemtrackProxy::MemtrackAidlInstance()) {}
+MemtrackProxy::MemtrackProxy() {
+    memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance();
+
+    // Only check for a HIDL implementation if we failed to get the AIDL service
+    if (!memtrack_aidl_instance_) {
+        memtrack_hidl_instance_ = MemtrackProxy::MemtrackHidlInstance();
+    }
+}
 
 ndk::ScopedAStatus MemtrackProxy::getMemory(int pid, MemtrackType type,
                                             std::vector<MemtrackRecord>* _aidl_return) {
diff --git a/services/sensorservice/aidl/fuzzer/fuzzer.cpp b/services/sensorservice/aidl/fuzzer/fuzzer.cpp
index 1b63d76..ee8ceb3 100644
--- a/services/sensorservice/aidl/fuzzer/fuzzer.cpp
+++ b/services/sensorservice/aidl/fuzzer/fuzzer.cpp
@@ -16,7 +16,7 @@
 #include <fuzzbinder/libbinder_ndk_driver.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
-#include <ServiceManager.h>
+#include <fakeservicemanager/FakeServiceManager.h>
 #include <android-base/logging.h>
 #include <android/binder_interface_utils.h>
 #include <fuzzbinder/random_binder.h>
@@ -29,7 +29,7 @@
 [[clang::no_destroy]] static std::once_flag gSmOnce;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    static android::sp<android::ServiceManager> fakeServiceManager = new android::ServiceManager();
+    static android::sp<android::FakeServiceManager> fakeServiceManager = new android::FakeServiceManager();
     std::call_once(gSmOnce, [&] { setDefaultServiceManager(fakeServiceManager); });
     fakeServiceManager->clear();